/* ─── PaperTek-profilen v3.3 — delt av appen og boka ─────────────────────────
   Kjelde: PaperTek Design Tokens v3.3 (designmanual 3.3, 10.10.2026) og
   Leksihjelp-redesignet (dysleksi og tilgjenge som krav, ikkje tillegg).

   Fila har TO delar:
     1. Skrifta og fargevariablane (--pt-*). Dei gjer ingenting åleine.
     2. Profilreglane for alle sider som lastar fila (leksjonar, knutepunkt, skal,
        trenarar, Konkurranse, lærar- og infosider), avgrensa til
        html[data-profil="v33"] (sett av js/profil-flagg.js).
   Boka les berre del 1 (print-viewer.html); bokregelane står i
   back-stage/print-generator-2.0/styles/profil-v33.css.

   ⚠️ Kvar tekstfarge har minst 4,5:1 mot flata ho står på, i lys og mørk modus.
   tests/unit/papertek-profil.test.js held det. Digital Teal (#11B49A),
   åtvaringsgult (#D3A000) og Soft Lime (#D6F07D) er ALDRI tekstfargar.
   ⚠️ Skrifta er sjølvhosta og precacha (sw.js) — appen er offline-først. */

/* Atkinson Hyperlegible, SIL Open Font License 1.1
   (bibliotek/fonts/OFL-AtkinsonHyperlegible.txt). I, l og 1 er ulike. */
@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('bibliotek/fonts/atkinson-hyperlegible-latin-400.woff2') format('woff2');
}

@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('bibliotek/fonts/atkinson-hyperlegible-latin-700.woff2') format('woff2');
}

:root {
  --pt-font: 'Atkinson Hyperlegible', 'Segoe UI', system-ui, sans-serif;

  /* Flater: Paper White og kvitt, kjølige tonar frå Deep Nordic Teal */
  --pt-bg: #FAFCFB;
  --pt-surface: #FFFFFF;
  --pt-surface-soft: #F4F7F6;
  --pt-tint: #EEF5F3;
  --pt-border: #DCE3E1;
  --pt-border-strong: #5A8185;
  --pt-field-border: #5A8185; /* skjemafelt: kanten ER feltet (WCAG 1.4.11), ≥ 3:1 mot alle flater */

  /* Tekst: mørk teal i staden for svart */
  --pt-ink: #14383C;
  --pt-ink-secondary: #3F5358;
  --pt-heading: #0B3E44;
  --pt-accent: #137A88;
  --pt-link: #0D515D;

  /* Handling */
  --pt-primary: #0B3E44;
  --pt-on-primary: #FFFFFF;
  --pt-lime: #D6F07D;
  --pt-lime-mark: #E4F5A6;
  --pt-on-lime: #0B3E44; /* same i lys og mørk: lime er alltid lys */

  /* Status — berre for tilbakemelding, aldri pynt */
  --pt-positive: #28733B;
  --pt-positive-bg: #E7F3EA;
  --pt-negative: #B13D4A;
  --pt-negative-bg: #FBECEE;
  --pt-warning-ink: #6B4F00;
  --pt-warning-bg: #FBF3D6;

  /* Blyant- og stjernenivå (grøn, blå, rubin, gull): nivået er informasjon
     eleven les («Blåblyanten er din!»), ikkje status. Ikon: ≥ 3:1 mot alle flater. */
  --pt-blyant-gronn: #2B7A3D;
  --pt-blyant-bla: #2F5FB3;
  --pt-blyant-rubin: #A3264A;
  --pt-blyant-gull: #9C7300;

  /* Spelpanel (gradientar i appen): same i lys og mørk */
  --pt-panel: #0B3E44;
  --pt-on-panel: #FFFFFF;

  /* Fokus: dobbel ring, mørk innerst og lime ytst */
  --pt-focus-inner: #0B3E44;
  --pt-focus-outer: #D6F07D;
}

@media (prefers-color-scheme: dark) {
  /* «Følg enheten» (ingen data-tema): som før. «Lys» i Profil slår blokka av.
     Tvillingen under data-tema="mork" står rett under: tests/unit/fargetema-css.test.js */
  html[data-profil="v33"]:where(:not([data-tema="lys"])) {
    color-scheme: dark; /* native kontrollar og rullefelt følgjer (fase 3) */
    --pt-bg: #062B30;
    --pt-surface: #0B3E44;
    --pt-surface-soft: #0D474E;
    --pt-tint: #10525A;
    --pt-border: #285359;
    --pt-border-strong: #73999D;
    --pt-field-border: #8FB3B6; /* border-strong gav 2,85:1 mot tint */

    --pt-ink: #E6F2F1;
    --pt-ink-secondary: #B8D0CE;
    --pt-heading: #FFFFFF;
    --pt-accent: #88D4C2;
    --pt-link: #A5D3D6;

    --pt-primary: #D6F07D;
    --pt-on-primary: #062B30;
    --pt-lime: #D6F07D;
    --pt-lime-mark: #3A4A1A;

    --pt-positive: #88D4A0;
    --pt-positive-bg: #123A22;
    --pt-negative: #F2A8B1;
    --pt-negative-bg: #3D1A20;
    --pt-warning-ink: #F5D97A;
    --pt-warning-bg: #3A3010;

    --pt-blyant-gronn: #8FD9A3;
    --pt-blyant-bla: #8DB4F0;
    --pt-blyant-rubin: #F59BB8;
    --pt-blyant-gull: #F2C94C;

    --pt-focus-inner: #FFFFFF;
    --pt-focus-outer: #D6F07D;
  }
}

/* «Mørk» valt i Profil (data-tema frå js/profil-flagg.js): same verdiar som
   over, utan media-spørjinga. :where() held tyngda lik media-regelen.
   Spesifikasjon: docs/superpowers/specs/2026-10-15-fargetema-design.md */
html[data-profil="v33"]:where([data-tema="mork"]) {
  color-scheme: dark; /* native kontrollar og rullefelt følgjer (fase 3) */
  --pt-bg: #062B30;
  --pt-surface: #0B3E44;
  --pt-surface-soft: #0D474E;
  --pt-tint: #10525A;
  --pt-border: #285359;
  --pt-border-strong: #73999D;
  --pt-field-border: #8FB3B6; /* border-strong gav 2,85:1 mot tint */

  --pt-ink: #E6F2F1;
  --pt-ink-secondary: #B8D0CE;
  --pt-heading: #FFFFFF;
  --pt-accent: #88D4C2;
  --pt-link: #A5D3D6;

  --pt-primary: #D6F07D;
  --pt-on-primary: #062B30;
  --pt-lime: #D6F07D;
  --pt-lime-mark: #3A4A1A;

  --pt-positive: #88D4A0;
  --pt-positive-bg: #123A22;
  --pt-negative: #F2A8B1;
  --pt-negative-bg: #3D1A20;
  --pt-warning-ink: #F5D97A;
  --pt-warning-bg: #3A3010;

  --pt-blyant-gronn: #8FD9A3;
  --pt-blyant-bla: #8DB4F0;
  --pt-blyant-rubin: #F59BB8;
  --pt-blyant-gull: #F2C94C;

  --pt-focus-inner: #FFFFFF;
  --pt-focus-outer: #D6F07D;
}

/* Utskrift: papiret er lyst. I mørk modus (eininga eller «Mørk» i Profil) skreiv
   infosidene nesten kvit tekst (#E6F2F1) på #062B30, og utan bakgrunnsgrafikk i
   utskrifta blei det kvitt på kvitt. Under print får heile profilen dei lyse
   verdiane frå :root att. Same tyngd som dei to mørke formene over (0,1,1), og
   blokka står etter begge, så ho vinn over begge. Ingen data-tema her: dette er
   ikkje eit temaval (tests/unit/fargetema-css.test.js held verdiane lik :root). */
@media print {
  html[data-profil="v33"] {
    color-scheme: light;
    --pt-bg: #FAFCFB;
    --pt-surface: #FFFFFF;
    --pt-surface-soft: #F4F7F6;
    --pt-tint: #EEF5F3;
    --pt-border: #DCE3E1;
    --pt-border-strong: #5A8185;
    --pt-field-border: #5A8185;

    --pt-ink: #14383C;
    --pt-ink-secondary: #3F5358;
    --pt-heading: #0B3E44;
    --pt-accent: #137A88;
    --pt-link: #0D515D;

    --pt-primary: #0B3E44;
    --pt-on-primary: #FFFFFF;
    --pt-lime: #D6F07D;
    --pt-lime-mark: #E4F5A6;

    --pt-positive: #28733B;
    --pt-positive-bg: #E7F3EA;
    --pt-negative: #B13D4A;
    --pt-negative-bg: #FBECEE;
    --pt-warning-ink: #6B4F00;
    --pt-warning-bg: #FBF3D6;

    --pt-blyant-gronn: #2B7A3D;
    --pt-blyant-bla: #2F5FB3;
    --pt-blyant-rubin: #A3264A;
    --pt-blyant-gull: #9C7300;

    --pt-focus-inner: #0B3E44;
    --pt-focus-outer: #D6F07D;
  }
}

/* ═══ PROFILEN PÅ ALLE SIDER SOM LASTAR FILA (fase 3) ═══════════════════════
   Gjeld berre når html[data-profil="v33"] (js/profil-flagg.js: av i
   produksjon), på kvar side som lastar fila: leksjonar, knutepunkt og skal
   (fase 3), Ordtrenaren og trenarane (fase 4), Konkurranse (fase 5) og
   lærarvisingane og infosidene (fase 6). Leksjonsspesifikke reglar avgrensar på
   verdien av data-curriculum-id, sidespesifikke på data-side på <body>.
   tests/unit/papertek-profil.test.js krev at kvar regel er avgrensa slik.

   ⚠️ SPESIFISITET — tre lag, i denne rekkjefølgja:
   1. Fargeomlegging av Tailwind-klassar står i :where(…) og har SAME tyngd
      som Tailwind sjølv (0,1,0). Fila kjem etter Tailwind, så ho vinn over
      vanlege fargeklassar — men tilstandsklassane til modulane (.match-item
      .correct, .feedback-incorrect …) vinn over henne, slik dei gjer i dag.
      Ei sterkare omlegging ville teke tilstandane og gjort rett/gale nøytrale.
   2. Innanfor laget: flater → tekst → handling → STATUS sist, så raud/grøn
      alltid vinn over ein nøytral klasse på same element.
   3. !important berre der noko anna alt brukar det: spansk/fransk tema
      (layout/shell.js applyTheme), Tailwind sine !bg-*-klassar, fokus.
   ⚠️ Klassenamna blir ALDRI bytte — fargeklassar er òg tilstand og selektorar.
   ⚠️ Inget innhald blir endra; inline-fargar frå overlaya blir overstyrte her. */

/* Rota: gjeld alle sider som lastar profilen, ikkje berre leksjonane. */
html[data-profil="v33"] {
  font-size: 112.5%; /* 18 px brødtekst: alle rem-storleikar følgjer med */
  background: var(--pt-bg);
}

html[data-profil="v33"] body {
  font-family: var(--pt-font);
  background: var(--pt-bg);
  color: var(--pt-ink);
  line-height: 1.6;
  letter-spacing: 0.01em;
}

/* Ingen kursiv, ingen berre-store-bokstavar. Utheving blir feit skrift. */
html[data-profil="v33"] body *,
html[data-profil="v33"] body *::before,
html[data-profil="v33"] body *::after {
  font-style: normal !important;
  text-transform: none !important;
}
:where(html[data-profil="v33"] body) :is(em, i, .italic) { font-weight: 700; }
/* Éi skrift: teksttypane (brev o.a.) har font-serif — Atkinson òg der. */
:where(html[data-profil="v33"] body) :is(.font-serif, .font-mono) { font-family: var(--pt-font); }
:where(html[data-profil="v33"] body) :is(.tracking-tight, .tracking-wide, .tracking-wider, .tracking-widest) { letter-spacing: 0.01em; }

/* ── 1a. Flater ── */
:where(html[data-profil="v33"] body) :is(.bg-white) { background-color: var(--pt-surface); }
:where(html[data-profil="v33"] body) :is(.bg-stone-50, .bg-gray-50) { background-color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.bg-stone-100, .bg-stone-100\/60, .bg-slate-100, .bg-gray-100, .bg-amber-100\/60) { background-color: var(--pt-surface-soft); }
:where(html[data-profil="v33"] body) :is(.bg-amber-50, .bg-amber-100, .bg-orange-50, .bg-yellow-50, .bg-blue-50, .bg-blue-100, .bg-sky-50, .bg-sky-100, .bg-indigo-50, .bg-stone-200, .bg-gray-200) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.bg-stone-300, .bg-gray-300) { background-color: var(--pt-border); }
:where(html[data-profil="v33"] body) :is(.bg-rose-200, .bg-teal-200, .bg-sky-200, .bg-blue-200, .bg-green-200) { background-color: var(--pt-tint); color: var(--pt-ink); }
:where(html[data-profil="v33"] body) :is(.bg-pink-50, .bg-pink-100, .bg-teal-50, .bg-teal-100, .bg-cyan-100, .bg-lime-100, .bg-blue-100\/60, .bg-amber-50\/30, .bg-amber-500\/20, .bg-orange-100, .bg-yellow-100, .bg-rose-50, .bg-rose-100, .bg-white\/80, .bg-white\/90, .bg-white\/95) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-stone-50:hover) { background-color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-amber-50:hover, .hover\:bg-amber-100:hover, .hover\:bg-amber-200:hover, .hover\:bg-blue-100:hover, .hover\:bg-stone-100:hover, .hover\:bg-stone-200:hover) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-stone-300:hover) { background-color: var(--pt-border); }

/* ── 1b. Tekst ── */
:where(html[data-profil="v33"] body) :is(.text-stone-800, .text-stone-900, .text-gray-800, .text-gray-900) { color: var(--pt-ink); }
:where(html[data-profil="v33"] body) :is(.text-stone-300, .text-stone-400, .text-stone-500, .text-stone-600, .text-stone-700, .text-gray-400, .text-gray-500, .text-gray-600, .text-gray-700, .text-slate-600) { color: var(--pt-ink-secondary); }
:where(html[data-profil="v33"] body) :is(h1, h2, h3, h4):where(:not(.text-white *, [class*="bg-gradient-to"] *)) { color: var(--pt-heading); }
:where(html[data-profil="v33"] body) :is(.text-amber-700, .text-amber-800, .text-amber-900, .text-orange-700, .text-orange-800, .text-rose-800, .text-rose-900, .text-teal-900, .text-sky-900, .text-blue-900, .text-yellow-700, .text-yellow-800, .text-yellow-900) { color: var(--pt-heading); }
:where(html[data-profil="v33"] body) :is(.text-amber-500, .text-amber-600, .text-orange-500, .text-orange-600, .text-blue-600, .text-blue-700, .text-blue-800, .text-blue-900, .text-sky-700, .text-indigo-600, .text-indigo-700) { color: var(--pt-link); }
:where(html[data-profil="v33"] body) :is(.text-purple-500, .text-purple-600, .text-purple-700, .text-pink-700, .text-teal-600, .text-teal-700, .text-teal-800, .text-cyan-700, .text-sky-600, .text-sky-800) { color: var(--pt-link); }
:where(html[data-profil="v33"] body) :is(.hover\:text-stone-500:hover, .hover\:text-stone-600:hover, .hover\:text-stone-700:hover) { color: var(--pt-ink-secondary); }
:where(html[data-profil="v33"] body) :is(.hover\:text-stone-800:hover) { color: var(--pt-ink); }
:where(html[data-profil="v33"] body) :is(.hover\:text-amber-600:hover, .hover\:text-amber-700:hover, .hover\:text-amber-800:hover) { color: var(--pt-heading); }
/* Liten tekst blir brødtekst: 18 px for alle under profilen (eigaravgjerd 17.10, fase 7).
   Tailwind sin text-sm er 0,875rem (15,75 px under rota på 112,5 %), text-xs 0,75rem (13,5 px),
   og koden har nokre faste px-storleikar (botnmenyen og merkelappar: text-[10px]/[11px]).
   Tailwind set òg line-height (1,25rem/1rem), så linjehøgda blir 1,5 her. Låg tyngd (0,1,0,
   som Tailwind): profilen står sist og vinn over Tailwind, men ein komponentregel som gjer
   teksten STØRRE, vinn framleis. Følgjene (bryting, plass) står i «Fase 7: opprydding». */
:where(html[data-profil="v33"] body) :is(.text-sm, .text-xs, .text-\[10px\], .text-\[11px\]) { font-size: 1rem; line-height: 1.5; }
/* Stor tekst som ikkje er overskrift (tal i kapittelboblene, poengtal, «ich/du/er» i
   grammatikken): Tailwind gjev text-xl 1,4, text-2xl 1,33, text-3xl 1,2 og text-4xl 1,11 i
   linjehøgd. Brødtekstregelen er minst 1,5. Overskrifter står utanfor: linjehøgda deira er
   profilen sitt val. [class*=] tek òg md:text-2xl o.l. Same låge tyngd som løftet over. */
:where(html[data-profil="v33"] body) :is([class*="text-xl"], [class*="text-2xl"], [class*="text-3xl"], [class*="text-4xl"], [class*="text-5xl"], [class*="text-6xl"], [class*="text-7xl"], [class*="text-8xl"], [class*="text-9xl"]):where(:not(h1, h2, h3, h4, h5, h6, :is(h1, h2, h3, h4, h5, h6) *)) { line-height: 1.5; }

/* ── 1c. Handling ── */
:where(html[data-profil="v33"] body) :is(.bg-amber-500, .bg-amber-600, .bg-orange-500, .bg-orange-600, .bg-blue-500, .bg-blue-600, .bg-indigo-500, .bg-indigo-600) {
  background-color: var(--pt-primary);
  color: var(--pt-on-primary);
}
:where(html[data-profil="v33"] body) :is(.hover\:bg-amber-600:hover, .hover\:bg-amber-700:hover, .hover\:bg-blue-600:hover, .hover\:bg-blue-700:hover, .hover\:bg-indigo-700:hover) {
  background-color: var(--pt-primary);
  color: var(--pt-on-primary);
}
:where(html[data-profil="v33"] body) :is(.bg-sky-500, .bg-sky-600, .bg-purple-500, .bg-purple-600) {
  background-color: var(--pt-primary);
  color: var(--pt-on-primary);
}
:where(html[data-profil="v33"] body) :is(.hover\:bg-sky-600:hover, .hover\:bg-purple-600:hover, .hover\:bg-purple-700:hover) { background-color: var(--pt-primary); color: var(--pt-on-primary); }
:where(html[data-profil="v33"] body) :is(.bg-purple-50, .bg-purple-100) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.bg-stone-500, .bg-stone-600, .bg-gray-500) { background-color: var(--pt-ink-secondary); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-stone-400:hover, .hover\:bg-stone-600:hover) { background-color: var(--pt-ink-secondary); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.bg-amber-200, .bg-amber-300, .bg-amber-400) { background-color: var(--pt-lime); color: var(--pt-on-lime); }

/* ── 1c+. Fleire klassar som leksjonskoden brukar (klassedekningstesten) ── */
:where(html[data-profil="v33"] body) :is(.bg-indigo-100) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-blue-50:hover, .hover\:bg-blue-200:hover, .hover\:bg-gray-200:hover, .hover\:bg-indigo-50:hover, .hover\:bg-orange-50:hover, .hover\:bg-indigo-100:hover, .hover\:bg-purple-50:hover, .hover\:bg-sky-100:hover) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.bg-amber-700, .bg-amber-800, .bg-teal-500, .bg-indigo-700, .bg-orange-400, .bg-sky-400, .bg-teal-400, .bg-indigo-400) { background-color: var(--pt-primary); color: var(--pt-on-primary); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-orange-600:hover, .hover\:bg-indigo-600:hover, .hover\:bg-teal-600:hover) { background-color: var(--pt-primary); color: var(--pt-on-primary); }
:where(html[data-profil="v33"] body) :is(.bg-stone-700, .bg-stone-800, .bg-blue-900) { background-color: var(--pt-panel); color: var(--pt-on-panel); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-stone-700:hover, .hover\:bg-stone-800:hover) { background-color: var(--pt-panel); color: var(--pt-on-panel); }
:where(html[data-profil="v33"] body) :is(.bg-stone-400, .bg-gray-400) { background-color: var(--pt-ink-secondary); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-stone-500:hover, .hover\:bg-gray-500:hover) { background-color: var(--pt-ink-secondary); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.bg-yellow-400, .bg-yellow-500) { background-color: var(--pt-lime); color: var(--pt-on-lime); }
:where(html[data-profil="v33"] body) :is(.text-blue-500, .text-sky-500, .text-amber-400, .text-purple-400) { color: var(--pt-link); }
:where(html[data-profil="v33"] body) :is(.text-orange-900, .text-purple-800, .text-purple-900) { color: var(--pt-heading); }
:where(html[data-profil="v33"] body) :is(.hover\:text-amber-900:hover, .hover\:text-blue-900:hover) { color: var(--pt-heading); }
:where(html[data-profil="v33"] body) :is(.hover\:text-blue-800:hover, .hover\:text-sky-700:hover, .hover\:text-purple-600:hover, .hover\:text-purple-700:hover) { color: var(--pt-link); }
:where(html[data-profil="v33"] body) :is(.text-blue-100) { color: var(--pt-on-panel); }
:where(html[data-profil="v33"] body) :is(.text-amber-300) { color: var(--pt-lime); }
:where(html[data-profil="v33"] body) :is(.text-yellow-500) { color: var(--pt-warning-ink); }

/* ── 1d. Kantar ── */
/* Standardkanten: Tailwind sin preflight gjev alle element #e5e7eb, som er ein lys
   strek i mørk modus (theme.css viker for profilen på knutepunkta, fase 3).
   Same tyngd som preflight-regelen og seinare i kaskaden; kvar kantfargeklasse vinn. */
:where(html[data-profil="v33"] body) *,
:where(html[data-profil="v33"] body) *::before,
:where(html[data-profil="v33"] body) *::after { border-color: var(--pt-border); }
:where(html[data-profil="v33"] body) :is(.border-stone-100, .border-stone-200, .border-stone-300, .border-gray-200, .border-gray-300, .border-rose-300, .border-teal-300, .border-sky-200) { border-color: var(--pt-border); }
:where(html[data-profil="v33"] body) :is(.border-amber-100, .border-blue-100, .border-orange-100, .border-orange-200, .border-purple-100, .border-sky-100, .border-teal-100) { border-color: var(--pt-border); }
:where(html[data-profil="v33"] body) :is(.border-stone-400, .border-stone-500, .border-gray-400, .border-gray-500) { border-color: var(--pt-border-strong); }
:where(html[data-profil="v33"] body) :is(.border-amber-200, .border-amber-300, .border-amber-400, .border-amber-500, .border-amber-600, .border-blue-200, .border-blue-300, .border-blue-400, .border-blue-500, .border-indigo-500, .border-sky-500) { border-color: var(--pt-accent); }

/* Skjemafelt: kanten er det som viser feltet (WCAG 1.4.11, 3:1). --pt-border
   (1,3:1) er ein skiljestrek; felt får --pt-field-border. Første regel tek felt
   utan kantklasse (same tyngd som *-regelen over, seinare), andre tek dei
   nøytrale kantklassane (0,1,0). Begge står før statuslaget, så rett/gale og
   modulane sine tilstandsklassar vinn framleis. */
:where(html[data-profil="v33"] body) :where(input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]), select, textarea) { border-color: var(--pt-field-border); }
:where(html[data-profil="v33"] body) :where(input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]), select, textarea):is(.border-stone-100, .border-stone-200, .border-stone-300, .border-stone-400, .border-stone-500, .border-gray-200, .border-gray-300, .border-gray-400, .border-gray-500) { border-color: var(--pt-field-border); }

/* ── 1e. STATUS — sist i laget, så han vinn over nøytrale klassar ── */
:where(html[data-profil="v33"] body) :is(.text-green-500, .text-green-600, .text-green-700, .text-green-800, .text-green-900, .text-emerald-600, .text-emerald-700, .text-emerald-800) { color: var(--pt-positive); }
:where(html[data-profil="v33"] body) :is(.text-red-500, .text-red-600, .text-red-700, .text-red-800, .text-rose-500, .text-rose-700) { color: var(--pt-negative); }
:where(html[data-profil="v33"] body) :is(.hover\:text-green-900:hover) { color: var(--pt-positive); }
:where(html[data-profil="v33"] body) :is(.bg-green-50, .bg-green-100, .bg-green-200, .bg-green-300, .bg-emerald-50, .bg-emerald-100) { background-color: var(--pt-positive-bg); }
:where(html[data-profil="v33"] body) :is(.bg-red-50, .bg-red-100, .bg-red-200) { background-color: var(--pt-negative-bg); }
:where(html[data-profil="v33"] body) :is(.bg-green-100\/60) { background-color: var(--pt-positive-bg); }
/* Tidtakarflatene i ordkortknappane («Riktig nå» / «Kan ikke ennå») er `absolute inset-0` og ligg SIST
   i knappen, altså over etiketten: ei ugjennomsiktig flate skjuler teksten. Dei held difor 30 % dekning
   (Tailwind-intensjonen). Nettlesarar utan color-mix slepper erklæringa og beheld Tailwind sin eigen
   gjennomsiktige farge; det er greitt. Kvar klasse står åleine, ikkje i ei gruppe med ugjennomsiktige. */
:where(html[data-profil="v33"] body) :is(.bg-green-200\/30) { background-color: color-mix(in srgb, var(--pt-positive-bg) 30%, transparent); }
:where(html[data-profil="v33"] body) :is(.bg-orange-200\/30) { background-color: color-mix(in srgb, var(--pt-tint) 30%, transparent); }
/* Flata over etiketten vaskar ut teksten sjølv når ho er gjennomsiktig (målt 16.10: «Riktig nå» 5,10 → 2,92:1 i lys, 7,24 → 4,42:1 i mørk).
   Etikettane løftast difor over tidtakarflata; flata blir ståande som ein bakgrunnsfarge bak teksten. */
:where(html[data-profil="v33"] body) :is(#btn-action, #btn-next) > span:not([id^="timer-"]) { position: relative; z-index: 1; }
:where(html[data-profil="v33"] body) :is(.bg-red-100\/60) { background-color: var(--pt-negative-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-green-100:hover, .hover\:bg-green-200:hover) { background-color: var(--pt-positive-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-red-100:hover, .hover\:bg-red-200:hover) { background-color: var(--pt-negative-bg); }
:where(html[data-profil="v33"] body) :is(.bg-green-500, .bg-green-600) { background-color: var(--pt-positive); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.bg-red-500, .bg-red-600, .bg-rose-600) { background-color: var(--pt-negative); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-green-600:hover, .hover\:bg-green-700:hover) { background-color: var(--pt-positive); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.border-green-100, .border-green-200, .border-green-300, .border-green-400, .border-green-500, .border-green-600) { border-color: var(--pt-positive); }
:where(html[data-profil="v33"] body) :is(.border-red-200, .border-red-300, .border-red-400, .border-red-500, .border-red-600, .border-rose-200) { border-color: var(--pt-negative); }
:where(html[data-profil="v33"] body) :is(.border-yellow-500, .border-amber-700) { border-color: var(--pt-warning-ink); }
/* Peikar over (kantar): eigne liner. Ein :hover i ei :is()-liste gjev HEILE
   lista tyngd 0,2,0, og då slo t.d. .border-stone-400 rett/gale-kanten på felt. */
:where(html[data-profil="v33"] body) :is(.hover\:border-stone-300:hover) { border-color: var(--pt-border-strong); }
:where(html[data-profil="v33"] body) :is(.hover\:border-sky-200:hover, .hover\:border-sky-300:hover) { border-color: var(--pt-accent); }
:where(html[data-profil="v33"] body) :is(.hover\:border-green-200:hover) { border-color: var(--pt-positive); }
:where(html[data-profil="v33"] body) :is(.hover\:border-red-500:hover) { border-color: var(--pt-negative); }
/* Ringar: same roller som kantane over. Vald svar på testsida (ring-2
   ring-amber-500) var 2,15:1 mot kortet; laget som har tur i spela; fokus.
   Fokus- og peikar-variantane står på eigne liner (sjå over). */
:where(html[data-profil="v33"] body) :is(.ring-amber-400, .ring-amber-500, .ring-blue-300, .ring-blue-400, .ring-blue-500, .ring-indigo-500, .ring-purple-500) { --tw-ring-color: var(--pt-accent); }
:where(html[data-profil="v33"] body) :is(.ring-green-300, .ring-green-400, .ring-green-500, .ring-green-600) { --tw-ring-color: var(--pt-positive); }
:where(html[data-profil="v33"] body) :is(.ring-red-400) { --tw-ring-color: var(--pt-negative); }
:where(html[data-profil="v33"] body) :is(.ring-yellow-400) { --tw-ring-color: var(--pt-lime); }
:where(html[data-profil="v33"] body) :is(.focus\:ring-amber-500:focus, .focus\:ring-blue-400:focus, .focus\:ring-blue-500:focus, .focus\:ring-green-500:focus, .focus\:ring-sky-500:focus) { --tw-ring-color: var(--pt-accent); }
:where(html[data-profil="v33"] body) :is(.hover\:ring-amber-500:hover) { --tw-ring-color: var(--pt-accent); }

:where(html[data-profil="v33"] body) :is(.text-red-400, .hover\:text-red-600:hover, .hover\:text-red-700:hover) { color: var(--pt-negative); }
:where(html[data-profil="v33"] body) :is(.hover\:text-green-700:hover, .hover\:text-green-800:hover) { color: var(--pt-positive); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-green-50:hover) { background-color: var(--pt-positive-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-red-50:hover) { background-color: var(--pt-negative-bg); }
:where(html[data-profil="v33"] body) :is(.bg-green-700) { background-color: var(--pt-positive); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-red-600:hover, .hover\:bg-red-700:hover, .hover\:bg-rose-700:hover) { background-color: var(--pt-negative); color: var(--pt-bg); }

/* ── 2. Tilstandar frå stylesheet.css og modulane — profilfargar og teikn ──
   Same eller høgare tyngd enn originalreglane, og seinare i kaskaden. */
:where(html[data-profil="v33"] body) :is(.match-item, .answer-match-item).selected { background-color: var(--pt-lime); border-color: var(--pt-heading); color: var(--pt-on-lime); }
:where(html[data-profil="v33"] body) :is(.match-item, .answer-match-item, .image-match-item).correct { background-color: var(--pt-positive); border-color: var(--pt-positive); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.match-item, .answer-match-item, .image-match-item).incorrect { background-color: var(--pt-negative); border-color: var(--pt-negative); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) .image-match-item:is(.correct, .incorrect) { position: relative; }
:where(html[data-profil="v33"] body) .image-match-item:is(.correct, .incorrect)::after {
  position: absolute; top: 0.25rem; right: 0.25rem;
  min-width: 1.6rem; height: 1.6rem; border-radius: 9999px;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; color: var(--pt-bg);
}
:where(html[data-profil="v33"] body) .image-match-item.correct::after { content: "✓"; background: var(--pt-positive); }
:where(html[data-profil="v33"] body) .image-match-item.incorrect::after { content: "✗"; background: var(--pt-negative); }
:where(html[data-profil="v33"] body) .feedback-correct { border-color: var(--pt-positive); }
:where(html[data-profil="v33"] body) .feedback-incorrect { border-color: var(--pt-negative); }
/* Verbtrenaren og kjønnsspelet: rett og gale knapp får teikn (fargen kjem frå statuslaget) */
:where(html[data-profil="v33"] body) :is(.mc-btn, .artikkel-btn).bg-green-500::after { content: " ✓"; font-weight: 700; }
:where(html[data-profil="v33"] body) :is(.mc-btn, .artikkel-btn).bg-red-500::after { content: " ✗"; font-weight: 700; }
/* Finn feilen: gale trykk (600 ms) får teikn òg når hint manglar */
:where(html[data-profil="v33"] body) .tte-token.bg-red-100::after { content: " ✗"; font-weight: 700; }
/* Memory: eit funne par var berre dempa (opacity-60) — no full kontrast og ✓ */
:where(html[data-profil="v33"] body) .memory-card.matched { position: relative; opacity: 1; outline: 3px solid var(--pt-positive); outline-offset: -3px; }
:where(html[data-profil="v33"] body) .memory-card.matched::after { content: "✓"; position: absolute; top: 0.25rem; right: 0.4rem; color: var(--pt-positive); font-weight: 700; }
/* Spelmodus (Jeopardy o.a.): vald knapp var berre amber (2,15:1) */
html[data-profil="v33"] body .mode-btn.active { background-color: var(--pt-primary); color: var(--pt-on-primary); border-color: var(--pt-primary); }
html[data-profil="v33"] body .mode-btn.active::before { content: "✓ "; }
/* Minidialog: eldre bobler var dempa inline (opacity .4) under 4,5:1 */
html[data-profil="v33"] body :is([style*="opacity: 0.4"], [style*="opacity:.4"], [style*="opacity: .4"]) { opacity: 0.85 !important; filter: none !important; }

/* Felt kan ikkje ha ::after. Ein grøn/raud kant på eit felt får eit ✓/✗-ikon
   inne i feltet, så rett/gale ikkje berre blir vist med farge (WCAG 1.4.1).
   Nivåveljaren i knutepunktet er unntatt: shell.js gjev han kanten i
   språkfargen (border-red-500 på spansk), som ikkje er eit svar. :where()
   held tyngda uendra. */
:where(html[data-profil="v33"] body) :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-green-400, .border-green-500, .border-green-600, .feedback-correct) {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2328733B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.4em center;
  background-size: 1.1em;
  padding-right: 1.8em;
}
:where(html[data-profil="v33"] body) :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-red-400, .border-red-500, .border-red-600, .feedback-incorrect, .gap-input.border-amber-500, .grammar-input.border-amber-500) {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23B13D4A' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.4em center;
  background-size: 1.1em;
  padding-right: 1.8em;
}

/* Konjugasjonsrutenett: tilstandane står i ein <style> i øvingsmarkupen
   (exercises-content-loader.js), så profilreglane treng høgare tyngd. */
html[data-profil="v33"] body .cg-cell.cg-correct {
  border-color: var(--pt-positive) !important;
  background: var(--pt-positive-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2328733B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E") no-repeat right 0.3em center / 1em !important;
  color: var(--pt-ink) !important;
  padding-right: 1.6em;
}
html[data-profil="v33"] body .cg-cell.cg-incorrect {
  border-color: var(--pt-negative) !important;
  background: var(--pt-negative-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23B13D4A' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") no-repeat right 0.3em center / 1em !important;
  color: var(--pt-ink) !important;
  padding-right: 1.6em;
}

/* Quiz og rett/gale: Tailwind sine !bg-*-klassar og quiz.css brukar !important. */
html[data-profil="v33"] body :is(.quiz-option.correct-answer, .quiz-option.correct-answer-temp, .tf-btn.\!bg-green-500) {
  background-color: var(--pt-positive) !important;
  border-color: var(--pt-positive) !important;
  color: var(--pt-bg) !important;
  opacity: 1 !important;
}
html[data-profil="v33"] body :is(.quiz-option.wrong-answer, .tf-btn.\!bg-red-500) {
  background-color: var(--pt-negative) !important;
  border-color: var(--pt-negative) !important;
  color: var(--pt-bg) !important;
}
html[data-profil="v33"] body :is(.quiz-option.correct-answer, .quiz-option.correct-answer-temp, .tf-btn.\!bg-green-500)::after { content: " ✓"; font-weight: 700; }
html[data-profil="v33"] body :is(.quiz-option.wrong-answer, .tf-btn.\!bg-red-500)::after { content: " ✗"; font-weight: 700; }

/* Spansk og fransk: layout/shell.js applyTheme set eigne fargar med !important.
   Ingen språkfargar i profilen (Geir 13.10). */
html[data-profil="v33"] body :is(.bg-amber-500, .bg-indigo-500, .bg-indigo-600) { background-color: var(--pt-primary) !important; color: var(--pt-on-primary) !important; }
html[data-profil="v33"] body :is(.hover\:bg-amber-600:hover, .hover\:bg-indigo-700:hover) { background-color: var(--pt-primary) !important; color: var(--pt-on-primary) !important; }
html[data-profil="v33"] body :is(.text-amber-500, .text-indigo-500, .text-indigo-600) { color: var(--pt-link) !important; }
html[data-profil="v33"] body :is(.border-amber-500, .border-indigo-500) { border-color: var(--pt-accent) !important; }
/* Ein inaktiv knapp skal sjå inaktiv ut. Regelane over (!important) slo
   Tailwind sin disabled:bg-stone-300, så «Neste» på testsida såg aktiv ut før
   eleven hadde svart. Inaktive kontrollar er unntatt kontrastkravet. Står
   etter peikar-regelen: same tyngd, så denne vinn òg under peikaren. */
html[data-profil="v33"] body :is(.bg-amber-500, .bg-indigo-500, .bg-indigo-600, .bg-stone-500, .bg-stone-600):disabled { background-color: var(--pt-border) !important; color: var(--pt-ink-secondary) !important; }
/* Verktøykorta har hover:ring-indigo-500; applyTheme gjer ringen raud (!important). */
html[data-profil="v33"] body .hover\:ring-indigo-500:hover { --tw-ring-color: var(--pt-accent) !important; }
/* Kvitt barn i ei flate profilen fargar om (t.d. haka i «Dette har du lært»:
   <span class="text-white">✓</span> i .check-box.bg-amber-500). I mørk modus
   er flata lys (lime/grøn), og kvitt på lime var 1,26:1. Barnet tek flata sin
   eigen tekstfarge, som er kontrasttesta. Berre direkte barn utan eiga flate. */
html[data-profil="v33"] body :is(.bg-amber-500, .bg-indigo-500, .bg-indigo-600, .bg-green-500, .bg-green-600, .bg-red-500, .bg-red-600, .bg-rose-600) > .text-white:not([class*="bg-"]) { color: inherit; }
/* Feilmeldinga (error-handler.js): lukkeknappen er kvit inne i ei raud flate
   som profilen fargar om; ho tek flata sin tekstfarge, òg ved peikar over. */
html[data-profil="v33"] body #error-toast button:is(.text-white, .hover\:text-gray-200:hover) { color: inherit; }

/* ── Faste fargar i stylesheet.css ── */
:where(html[data-profil="v33"] body) :is(#grammatikk th, #grammatikk td) { border-bottom-color: var(--pt-border); }
html[data-profil="v33"] body #grammatikk thead th {
  background-color: var(--pt-surface-soft);
  color: var(--pt-heading);
  border-color: var(--pt-border-strong);
}
:where(html[data-profil="v33"] body) .clickable-word { background-color: var(--pt-surface-soft); border-color: var(--pt-border-strong); color: var(--pt-ink); }
/* Peikar over: stylesheet.css gjev #e7e5e4 (0,2,0), og i mørk modus stod lys
   tekst på lys flate, 1,10:1 (setningsbygging på testsida). */
html[data-profil="v33"] body .clickable-word:hover { background-color: var(--pt-tint); border-color: var(--pt-accent); }
/* Ordtipset har mørk fast bakgrunn i stylesheet.css; innhaldet blir omfarga
   til profilen, så tipset får profilflata. */
html[data-profil="v33"] body #grammar-tooltip {
  background-color: var(--pt-surface);
  color: var(--pt-ink);
  border: 1px solid var(--pt-border-strong);
}
html[data-profil="v33"] body #grammar-tooltip :is(.tooltip-title, .tooltip-gender) { color: var(--pt-heading); }
html[data-profil="v33"] body #grammatikk tbody tr:hover { background-color: var(--pt-tint); }

/* ── Skjemafelt: eiga flate og tekstfarge (låg tyngd: tilstandar vinn) ── */
:where(html[data-profil="v33"] body) input:where(:not([type="checkbox"]):not([type="radio"]):not([type="hidden"])),
:where(html[data-profil="v33"] body) textarea,
:where(html[data-profil="v33"] body) select {
  background-color: var(--pt-surface);
  color: var(--pt-ink);
}
html[data-profil="v33"] body ::placeholder {
  color: var(--pt-ink-secondary);
  opacity: 1;
}

/* ── Gradientar ──
   Lyse gradientar (from-*-50/100) er lesepanel: dei får profilflata, og
   teksten følgjer dei vanlege reglane. Mørke gradientar (from-*-400…700) er
   spelhovud: fast panel i Deep Nordic Teal med lys tekst i begge modusar;
   element med eigen bakgrunn (merke, kort) beheld fargane sine.
   [class~="…"] treffer heile klassenamnet (from-amber-50 ≠ from-amber-500). */
:where(html[data-profil="v33"] body) [class*="bg-gradient-to"]:is([class~="from-amber-50"], [class~="from-amber-100"], [class~="from-orange-50"], [class~="from-orange-100"], [class~="from-yellow-50"], [class~="from-yellow-100"], [class~="from-indigo-50"], [class~="from-indigo-100"], [class~="from-sky-50"], [class~="from-sky-100"], [class~="from-blue-50"], [class~="from-blue-100"], [class~="from-purple-50"], [class~="from-purple-100"], [class~="from-pink-50"], [class~="from-pink-100"], [class~="from-green-50"], [class~="from-green-100"], [class~="from-stone-50"], [class~="from-stone-100"], [class~="from-slate-50"], [class~="from-slate-100"], [class~="from-gray-50"], [class~="from-gray-100"]) {
  background-image: none;
  background-color: var(--pt-tint);
}
:where(html[data-profil="v33"] body) [class*="bg-gradient-to"]:is([class~="from-orange-400"], [class~="from-orange-500"], [class~="from-orange-600"], [class~="from-red-500"], [class~="from-red-600"], [class~="from-yellow-400"], [class~="from-amber-400"], [class~="from-amber-500"], [class~="from-amber-600"], [class~="from-blue-500"], [class~="from-blue-600"], [class~="from-blue-700"], [class~="from-indigo-500"], [class~="from-indigo-600"], [class~="from-indigo-700"], [class~="from-purple-500"], [class~="from-purple-600"], [class~="from-sky-500"], [class~="from-sky-600"], [class~="from-green-500"], [class~="from-green-600"], [class~="from-teal-500"], [class~="from-teal-600"]) {
  background-image: none;
  background-color: var(--pt-panel);
  color: var(--pt-on-panel);
}
:where(html[data-profil="v33"] body) [class*="bg-gradient-to"]:is([class~="from-orange-400"], [class~="from-orange-500"], [class~="from-orange-600"], [class~="from-red-500"], [class~="from-red-600"], [class~="from-yellow-400"], [class~="from-amber-400"], [class~="from-amber-500"], [class~="from-amber-600"], [class~="from-blue-500"], [class~="from-blue-600"], [class~="from-blue-700"], [class~="from-indigo-500"], [class~="from-indigo-600"], [class~="from-indigo-700"], [class~="from-purple-500"], [class~="from-purple-600"], [class~="from-sky-500"], [class~="from-sky-600"], [class~="from-green-500"], [class~="from-green-600"], [class~="from-teal-500"], [class~="from-teal-600"]) > *:not([class*="bg-"]),
:where(html[data-profil="v33"] body) [class*="bg-gradient-to"]:is([class~="from-orange-400"], [class~="from-orange-500"], [class~="from-orange-600"], [class~="from-red-500"], [class~="from-red-600"], [class~="from-yellow-400"], [class~="from-amber-400"], [class~="from-amber-500"], [class~="from-amber-600"], [class~="from-blue-500"], [class~="from-blue-600"], [class~="from-blue-700"], [class~="from-indigo-500"], [class~="from-indigo-600"], [class~="from-indigo-700"], [class~="from-purple-500"], [class~="from-purple-600"], [class~="from-sky-500"], [class~="from-sky-600"], [class~="from-green-500"], [class~="from-green-600"], [class~="from-teal-500"], [class~="from-teal-600"]) > *:not([class*="bg-"]) > *:not([class*="bg-"]) {
  color: var(--pt-on-panel);
}

/* ── Avkryssingsboks og radioknapp: etiketten er trykkflata, minst 44 px ── */
html[data-profil="v33"] body label:has(input:is([type="radio"], [type="checkbox"])),
html[data-profil="v33"] body :is(input[type="radio"], input[type="checkbox"]) ~ label[for] {
  min-height: 44px;
}
/* Ein etikett med eigen visningsklasse held han og si eiga justering: «Aktiver hjelpemodus»
   (label.flex.items-start) vart inline-flex og sentrert (fase 7). */
html[data-profil="v33"] body label:has(input:is([type="radio"], [type="checkbox"])):not(.hidden, .block, .flex, .grid),
html[data-profil="v33"] body :is(input[type="radio"], input[type="checkbox"]) ~ label[for]:not(.hidden, .block, .flex, .grid) {
  display: inline-flex;
  align-items: center;
}

/* ── «Fra boka»-svar (FASIT_FARGE i book-blocks-render.js, berre på [data-blank]). Når
   nettlesaren har skrive stilen om (renderaren set line-height på span/div-felta), står
   fargen som rgb(), ikkje hex — begge må treffast. !important slår inline-fargen.
   Fargereglane for innhaldet under («Fra boka»: inline-fargane) står utan [data-blank]:
   før vann dei, så svar i tabellceller (hex) stod i overskriftsfarge og fekk aksentkant,
   medan svar i liner (rgb) stod i aksent (fase 7). ── */
html[data-profil="v33"] body .tab-content [data-blank]:is([style*="#b45309" i], [style*="rgb(180, 83, 9)" i]) {
  color: var(--pt-accent) !important;
}

/* ── Oppslagsord og grammatikkord: prikkstreken følgjer profilen ── */
:where(html[data-profil="v33"] body) .word-lookup { border-bottom-color: var(--pt-accent); }
:where(html[data-profil="v33"] body) .grammar-term { border-bottom-color: var(--pt-border-strong); }

/* ── Faner ── */
:where(html[data-profil="v33"] body) .tab-button { color: var(--pt-ink-secondary); }
:where(html[data-profil="v33"] body) .tab-button:hover { color: var(--pt-heading); }
html[data-profil="v33"] body .tab-button.active {
  color: var(--pt-heading);
  border-color: var(--pt-accent);
}

/* ── Trykkflater ≥ 44 × 44 px (lenkjer i løpande tekst er unntatt) ── */
html[data-profil="v33"] body :is(button, [role="button"], select, input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]), textarea) {
  min-height: 44px;
  min-width: 44px;
}
html[data-profil="v33"] body a[href]:not(:is(p, li, td, span) a) {
  min-height: 44px;
  min-width: 44px;
}
/* min-height verkar ikkje på ei inline-lenkje, så ho blir inline-flex. Ei lenkje med eigen
   visningsklasse (hidden, block, flex, grid, md:hidden …) held han: før tvinga regelen
   inline-flex på alle utanom .hidden og .block, så md:hidden og flex vart overkøyrde (fase 7). */
html[data-profil="v33"] body a[href]:not(:is(p, li, td, span) a):not(.hidden, .block, .flex, .grid, .contents, .table, [class*=":hidden"], [class*=":block"], [class*=":flex"], [class*=":grid"]) {
  display: inline-flex;
  align-items: center;
}

/* «Dette har du lært»: heile rada er trykkflata (lessons-content-loader.js) */
html[data-profil="v33"] body #checklist li { min-height: 44px; }

/* «Hopp til hovedinnhold» (accessibility.js) står på top: -40px. Med 44 px-
   regelen over er ho 44,8 px høg, så ei svart stripe stakk 5 px ned i
   vindauget på kvar side. Botnkanten står no i overkanten av vindauget, kor
   høg ho enn er (translateY(-100%) let ei halv pikselrad blø inn), og ho kjem
   fram ved fokus. */
html[data-profil="v33"] body .skip-link { top: auto; bottom: 100%; }
html[data-profil="v33"] body .skip-link:focus { top: 0; bottom: auto; }

/* ── Reflow på 320 px (WCAG 1.4.10): rader med 44 px-knappar brytast, ord som
   er lengre enn ei heil line, kan delast ── */
html[data-profil="v33"] body .special-chars-placeholder { flex-wrap: wrap; }
/* break-word, IKKJE anywhere: anywhere senkar minstebreidda til éin bokstav, så
   tabellkolonnar og knappar krympa og delte «du», «Galt» og «Akkusativ» midt i
   ordet (2 548 delte ord i tysk1-vg1 på 320 px, målt 14.10). Utan profilen var
   det null. break-word deler berre eit ord som ikkje får plass på ei line i det
   heile; tabellane står i overflow-x-auto og rullar i eigen boks. Ikkje
   hyphens: auto: då deler nettlesaren vanlege ord i løpande tekst ved
   lineslutt, og det er like tungt å lese (prøvd og målt 14.10). */
html[data-profil="v33"] body :is(h1, h2, h3, h4) { overflow-wrap: break-word; }
html[data-profil="v33"] body .tab-content { overflow-wrap: break-word; }
/* Med break-word krympar ikkje eit flex-barn under det lengste ordet sitt
   (anywhere skjulte dette ved å la alt krympe til éin bokstav). Rader som
   elles skuvar sida breiare på 320 px: */
html[data-profil="v33"] body .tab-content .flex-1 { min-width: 0; }
/* Klasseromsdialogen: 🖥️ + tittel + 📚 i ei sentrert rad (classroom-dialog-loader.js) */
html[data-profil="v33"] body #classroom-dialog-container .flex.justify-center { flex-wrap: wrap; }
/* Tekst-div utan klasse i ei flex-rad (t.d. modulknappane i grammatikken:
   ikon + «Wechselpräpositionen»): må kunne krympe, elles skuvar ordet rada ut. */
html[data-profil="v33"] body .tab-content .flex > div:not([class]) { min-width: 0; }
/* Rutenett utan kolonnemal under md (t.d. «grid md:grid-cols-2» med lydspelar
   og dialog i Leksjon-fana) har ein auto-kolonne som veks til det lengste ordet. */
html[data-profil="v33"] body .tab-content .grid > * { min-width: 0; }
/* Rader som brytast: barna skal aldri vere breiare enn rada (t.d. «(femten/
   seksten/sytten/…)» etter eit utfyllingsfelt — eitt «ord» med skråstrekar). */
html[data-profil="v33"] body .tab-content .flex-wrap > * { max-width: 100%; }
/* Tittel + merke (øvingshovudet): merka går under tittelen når det er trongt. */
html[data-profil="v33"] body .tab-content .flex:has(> h3) { flex-wrap: wrap; }
/* Lydspelaren: rada med 44 px-knappar brytast. */
html[data-profil="v33"] body .tab-content .audio-player { flex-wrap: wrap; }
/* Lenkjeknappar (t.d. «Last ned prosjektguide …» i lærarfana) */
html[data-profil="v33"] body .tab-content a[href] { max-width: 100%; }
/* Ordkort: to kolonnar på 320 px gir om lag 96 px tekstbreidd, og
   «Schwester» på 18 px fekk knapt plass. Mindre luft på dei smalaste
   skjermane (under), og eit ord som framleis er lengre enn kortet
   («die Geschichtshausaufgabe»), blir delt i staden for å flyte ut av kortet. */
html[data-profil="v33"] body .tab-content :is(.flashcard-front, .flashcard-back) { overflow-wrap: anywhere; }
/* Bingo: brettet er eit todimensjonalt spel, som Jeopardy. På smale skjermar
   får det ei minstebreidd og rullar i sitt eige kort. Uttrykka får plass i
   rutene, og sida blir ikkje brei. */
html[data-profil="v33"] body .tab-content :has(> .bingo-board) { overflow-x: auto; }
/* Faste breidder i øvingsdataa (t.d. w-80 = 320 px i spansk 10-2/10-3) skal
   ikkje gjere sida breiare enn skjermen. */
html[data-profil="v33"] body .tab-content :is(input, textarea, select) { max-width: 100%; }
/* Grammatikkverktøya står i ein sentrert flex-boks (grammar-renderer.js);
   utan min-width: 0 kan ikkje verktøyet krympe under innhaldet sitt. */
html[data-profil="v33"] body [id^="tool-"] > * { min-width: 0; max-width: 100%; }
/* Verb-splittaren: ordet kan ikkje brytast utan at oppgåva mistar meininga
   (eleven skal finne delepunktet). Rulling i ordboksen, aldri i sida. */
html[data-profil="v33"] body [id^="tool-separable-verbs"] .inline-flex.font-mono { max-width: 100%; overflow-x: auto; }
/* Jeopardy: brettet er eit todimensjonalt spel (unnateke i WCAG 1.4.10).
   Kolonnane er repeat(N, 1fr) inline, så brettet rullar i seg sjølv i staden
   for at sida blir brei, og kategorinamna blir ikkje delte bokstav for bokstav. */
html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 { overflow-x: auto; }
@media (max-width: 639.98px) {
  html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 { padding: 0.5rem; }
  /* Heile ord og tal i brettet («100», kategorinamna), og brettet rullar. */
  html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 > .grid > div {
    padding: 0.5rem 0.375rem;
    font-size: 1rem;
    letter-spacing: normal;
    overflow-wrap: normal;
  }
  html[data-profil="v33"] body .jeopardy-game .jeopardy-tile {
    padding: 0.75rem 0.5rem;
    min-height: 64px;
    font-size: 1.5rem;
    overflow-wrap: normal;
    white-space: nowrap;
  }
  html[data-profil="v33"] body [id^="tool-separable-verbs"] .inline-flex.font-mono { font-size: 1.25rem; letter-spacing: normal; }
  html[data-profil="v33"] body .tab-content .bingo-board { min-width: 34rem; }
  html[data-profil="v33"] body .tab-content .bingo-cell > span { font-size: 1rem; }
}
@media (max-width: 419.98px) {
  /* Ingen mindre skrift (fase 7: 18 px): mindre luft i kortet og mellom korta i staden. */
  html[data-profil="v33"] body .tab-content :is(.flashcard-front, .flashcard-back) { padding: 0.25rem; }
  html[data-profil="v33"] body .tab-content .grid:has(> .flashcard) { gap: 0.5rem; }
  html[data-profil="v33"] body [id^="tool-separable-verbs"] .inline-flex.font-mono > span { padding-inline: 0.125rem; }
}
/* Kronologi: tal i tomme plassar var dempa til 20 % (1,4:1). Dei viser kva
   plass ein hendig skal på, så dei treng å kunne lesast. */
html[data-profil="v33"] body .timeline-slot > .opacity-20 { opacity: 1; color: var(--pt-ink-secondary); }

/* ── Fokus: dobbel ring, mørk innerst og lime ytst ── */
html[data-profil="v33"] body :focus-visible {
  outline: 3px solid var(--pt-focus-inner) !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--pt-focus-outer) !important;
}

/* ── «Fra boka»: inline-fargane frå overlaya, overstyrte utan å røre dataa ──
   Berre i leksjonsinnhaldet (.tab-content) og i ressurssidene som rendrar
   same modular (grammatikk.html o.a., fase 3): modalar som «Hva er nytt?» har
   eigne inline-fargar som skal stå (sluttgjennomgangen, fase 2).
   [id="…"] i staden for #id: same tyngd som .tab-content, så rekkjefølgja mot
   andre !important-reglar er uendra på leksjonssidene.
   Kvar verdi står i hex og i rgb(): når eit skript rører stilen (t.d. line-height på
   «Fra boka»-felta), skriv nettlesaren heile attributtet om til «color: rgb(180, 83, 9)».
   i-flagget tek store bokstavar (#B45309) og eigenskapsnamn som er skrivne annleis (fase 7).
   !important slår inline-stilane. */
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="#b45309" i], [style*="rgb(180, 83, 9)" i], [style*="#92400e" i], [style*="rgb(146, 64, 14)" i], [style*="#78350f" i], [style*="rgb(120, 53, 15)" i], [style*="#d97706" i], [style*="rgb(217, 119, 6)" i], [style*="#f59e0b" i], [style*="rgb(245, 158, 11)" i]):not(:where([data-blank])) { color: var(--pt-heading) !important; border-color: var(--pt-accent) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="#a8a29e" i], [style*="rgb(168, 162, 158)" i], [style*="#78716c" i], [style*="rgb(120, 113, 108)" i], [style*="#57534e" i], [style*="rgb(87, 83, 78)" i], [style*="#9ca3af" i], [style*="rgb(156, 163, 175)" i]) { color: var(--pt-ink-secondary) !important; border-color: var(--pt-border-strong) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="color:#1c1917" i], [style*="color: #1c1917" i], [style*="color: rgb(28, 25, 23)" i], [style*="color:#292524" i], [style*="color: #292524" i], [style*="color: rgb(41, 37, 36)" i], [style*="color:#333" i], [style*="color: #333" i], [style*="color: rgb(51, 51, 51)" i]) { color: var(--pt-ink) !important; }
/* Inline lyse bakgrunnar i innhaldsdataa (grammatikk, spesialsider) —
   alle fire skrivemåtane (background/-color, med og utan mellomrom), og rgb() etter omskriving. */
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="background:#fafafa" i], [style*="background: #fafafa" i], [style*="background-color:#fafafa" i], [style*="background-color: #fafafa" i], [style*="background: rgb(250, 250, 250)" i], [style*="background-color: rgb(250, 250, 250)" i], [style*="background:#f3f4f6" i], [style*="background: #f3f4f6" i], [style*="background-color:#f3f4f6" i], [style*="background-color: #f3f4f6" i], [style*="background: rgb(243, 244, 246)" i], [style*="background-color: rgb(243, 244, 246)" i], [style*="background:#fafaf9" i], [style*="background: #fafaf9" i], [style*="background-color:#fafaf9" i], [style*="background-color: #fafaf9" i], [style*="background: rgb(250, 250, 249)" i], [style*="background-color: rgb(250, 250, 249)" i], [style*="background:#f5f5f4" i], [style*="background: #f5f5f4" i], [style*="background-color:#f5f5f4" i], [style*="background-color: #f5f5f4" i], [style*="background: rgb(245, 245, 244)" i], [style*="background-color: rgb(245, 245, 244)" i]) { background: var(--pt-surface-soft) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="background:#fff" i], [style*="background: #fff" i], [style*="background-color:#fff" i], [style*="background-color: #fff" i], [style*="background: rgb(255, 255, 255)" i], [style*="background-color: rgb(255, 255, 255)" i], [style*="background:white" i], [style*="background: white" i], [style*="background-color:white" i], [style*="background-color: white" i]) { background: var(--pt-surface) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="background:#dcfce7" i], [style*="background: #dcfce7" i], [style*="background-color:#dcfce7" i], [style*="background-color: #dcfce7" i], [style*="background: rgb(220, 252, 231)" i], [style*="background-color: rgb(220, 252, 231)" i], [style*="background:#ecfdf5" i], [style*="background: #ecfdf5" i], [style*="background-color:#ecfdf5" i], [style*="background-color: #ecfdf5" i], [style*="background: rgb(236, 253, 245)" i], [style*="background-color: rgb(236, 253, 245)" i], [style*="background:#e8f4e8" i], [style*="background: #e8f4e8" i], [style*="background-color:#e8f4e8" i], [style*="background-color: #e8f4e8" i], [style*="background: rgb(232, 244, 232)" i], [style*="background-color: rgb(232, 244, 232)" i]) { background: var(--pt-positive-bg) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="background:#dbeafe" i], [style*="background: #dbeafe" i], [style*="background-color:#dbeafe" i], [style*="background-color: #dbeafe" i], [style*="background: rgb(219, 234, 254)" i], [style*="background-color: rgb(219, 234, 254)" i], [style*="background:#e3f2fd" i], [style*="background: #e3f2fd" i], [style*="background-color:#e3f2fd" i], [style*="background-color: #e3f2fd" i], [style*="background: rgb(227, 242, 253)" i], [style*="background-color: rgb(227, 242, 253)" i], [style*="background:#fffbeb" i], [style*="background: #fffbeb" i], [style*="background-color:#fffbeb" i], [style*="background-color: #fffbeb" i], [style*="background: rgb(255, 251, 235)" i], [style*="background-color: rgb(255, 251, 235)" i], [style*="background:#fef3c7" i], [style*="background: #fef3c7" i], [style*="background-color:#fef3c7" i], [style*="background-color: #fef3c7" i], [style*="background: rgb(254, 243, 199)" i], [style*="background-color: rgb(254, 243, 199)" i]) { background: var(--pt-tint) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="background:#fef2f2" i], [style*="background: #fef2f2" i], [style*="background-color:#fef2f2" i], [style*="background-color: #fef2f2" i], [style*="background: rgb(254, 242, 242)" i], [style*="background-color: rgb(254, 242, 242)" i]) { background: var(--pt-negative-bg) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="background:#fde68a" i], [style*="background: #fde68a" i], [style*="background-color:#fde68a" i], [style*="background-color: #fde68a" i], [style*="background: rgb(253, 230, 138)" i], [style*="background-color: rgb(253, 230, 138)" i]) { background: var(--pt-lime) !important; color: var(--pt-on-lime) !important; }
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) :is([style*="color:#334155" i], [style*="color: #334155" i], [style*="color: rgb(51, 65, 85)" i], [style*="color:#475569" i], [style*="color: #475569" i], [style*="color: rgb(71, 85, 105)" i], [style*="color:#1e293b" i], [style*="color: #1e293b" i], [style*="color: rgb(30, 41, 59)" i]) { color: var(--pt-ink) !important; }
/* Inline gradient i lyse oppgåvepanel (t.d. klede-oppgåva, #fffbeb → #fef3c7) */
html[data-profil="v33"] body :is(.tab-content, [id="grammatikk-container"], [id="landeskunde-container"], [id="uttale-container"], [id="ordliste-container"]) [style*="linear-gradient" i]:is([style*="#fffbeb" i], [style*="rgb(255, 251, 235)" i], [style*="#fef3c7" i], [style*="rgb(254, 243, 199)" i]) { background: var(--pt-tint) !important; }
/* Brev (lesetekst): signaturen i stylesheet.css */
:where(html[data-profil="v33"] body) .lesetekst-letter-body .letter-signoff { color: var(--pt-heading); }
/* «Fra boka»-seksjonen sjølv (stylesheet.css, .bokseksjon-*) */
:where(html[data-profil="v33"] body) .bokseksjon { background: var(--pt-surface); }
:where(html[data-profil="v33"] body) .bokseksjon-title { color: var(--pt-heading); }
:where(html[data-profil="v33"] body) .bokseksjon-hint { color: var(--pt-ink-secondary); }
:where(html[data-profil="v33"] body) .bokseksjon-chevron { color: var(--pt-accent); }
html[data-profil="v33"] body .bokseksjon-summary:hover { background: var(--pt-tint); }
:where(html[data-profil="v33"] body) .bokseksjon--innfelt { border-color: var(--pt-accent); }

/* ── Fase 3: sider med eigen <style> (rotportalen, fråkopla-sidene) ── */
html[data-profil="v33"] body[data-side="portal"] :is(h1, .card h2) { color: var(--pt-heading); }
html[data-profil="v33"] body[data-side="portal"] :is(.subtitle, .card p, .footer) { color: var(--pt-ink-secondary); }
html[data-profil="v33"] body[data-side="portal"] .card { background: var(--pt-surface); border-color: var(--pt-border); color: var(--pt-ink); }
/* Korta er lenkjer med tittel, tekst og pil under kvarandre: 44 px-regelen for
   lenkjer (inline-flex) ville lagt dei på éi rad. */
html[data-profil="v33"] body[data-side="portal"] .grid > a.card[href] { display: block; }
html[data-profil="v33"] body[data-side="portal"] .card:hover { border-color: var(--pt-accent); }
html[data-profil="v33"] body[data-side="portal"] :is(.card .arrow, .footer a) { color: var(--pt-link); }
html[data-profil="v33"] body[data-side="portal"] .banner { background: var(--pt-warning-bg); color: var(--pt-warning-ink); }
/* Storleikane i portalen sin <style> står i px (12–13 px) og følgjer ikkje
   rota på 112,5 %: skildringa i korta, botnteksten og staging-banneret er
   brødtekst (18 px, fase 7). */
html[data-profil="v33"] body[data-side="portal"] :is(.card p, .footer, .banner) { font-size: 1rem; }
html[data-profil="v33"] body[data-side="offline"] .container { background: var(--pt-surface); color: var(--pt-ink); }
html[data-profil="v33"] body[data-side="offline"] h1 { color: var(--pt-heading); }
html[data-profil="v33"] body[data-side="offline"] p { color: var(--pt-ink-secondary); }
html[data-profil="v33"] body[data-side="offline"] .btn,
html[data-profil="v33"] body[data-side="offline"] .btn:hover { background-color: var(--pt-primary); color: var(--pt-on-primary); }
/* Reflow på 320 px: to kort i breidda fekk ikkje plass («International», 18 px),
   og boksen på fråkopla-sida var 400 px + utfylling (content-box). */
@media (max-width: 419.98px) {
  html[data-profil="v33"] body[data-side="portal"] .grid { grid-template-columns: 1fr; }
}
html[data-profil="v33"] body[data-side="offline"] .container { box-sizing: border-box; }

/* ── Fase 3: den kombinerte kapitteltesten (test-kapittel-1-4.html, eigen <style>) ── */
html[data-profil="v33"] body[data-side="kapitteltest"] .question-card { background: var(--pt-surface); color: var(--pt-ink); }
html[data-profil="v33"] body[data-side="kapitteltest"] .question-number { color: var(--pt-heading); }
html[data-profil="v33"] body[data-side="kapitteltest"] .answer-option { background: var(--pt-surface-soft); border-color: var(--pt-border); color: var(--pt-ink); }
html[data-profil="v33"] body[data-side="kapitteltest"] .answer-option:hover { background: var(--pt-tint); border-color: var(--pt-accent); }
html[data-profil="v33"] body[data-side="kapitteltest"] .answer-option.correct { background: var(--pt-positive-bg); border-color: var(--pt-positive); }
html[data-profil="v33"] body[data-side="kapitteltest"] .answer-option.incorrect { background: var(--pt-negative-bg); border-color: var(--pt-negative); }
/* Rett/gale blir ikkje berre vist med farge (WCAG 1.4.1) */
html[data-profil="v33"] body[data-side="kapitteltest"] .answer-option.correct::after { content: " ✓"; font-weight: 700; color: var(--pt-positive); }
html[data-profil="v33"] body[data-side="kapitteltest"] .answer-option.incorrect::after { content: " ✗"; font-weight: 700; color: var(--pt-negative); }
html[data-profil="v33"] body[data-side="kapitteltest"] .feedback.correct { background: var(--pt-positive-bg); color: var(--pt-positive); }
html[data-profil="v33"] body[data-side="kapitteltest"] .feedback.incorrect { background: var(--pt-negative-bg); color: var(--pt-negative); }
/* Finpussen 14.10, punkt 8b: «Forrige» og «Neste» stod klistra saman på 320 px, og pila
   braut over teksten. Knappane held pila og ordet saman, og rada brytast. */
html[data-profil="v33"] body[data-side="kapitteltest"] :is(#prev-btn, #next-btn, #show-answer-btn) { white-space: nowrap; }
html[data-profil="v33"] body[data-side="kapitteltest"] .no-print > .flex.justify-between { flex-wrap: wrap; gap: 0.75rem; }
@media (max-width: 479.98px) {
  html[data-profil="v33"] body[data-side="kapitteltest"] :is(#prev-btn, #next-btn) { padding-inline: 1rem; }
}

/* ── Fase 3: knutepunkta (layout/shell.js) — same utsjånad på alle tre språka ──
   shell.js vel aksentfargen etter språket: raud på spansk, raud «Fortsett» på
   fransk. Raudt er «gale» i profilen, så desse elementa får same rolle som på
   tysk (ingen språkfargar). Berre elementa shell.js fargar etter tema: raude
   feilmeldingar og slettknappar elles på sida er status og står. */
html[data-profil="v33"] body :is(#install-btn, #continue-btn, #download-media-btn, #offline-progress-fill) { background-color: var(--pt-primary); color: var(--pt-on-primary); }
html[data-profil="v33"] body #curriculum-selector { border-color: var(--pt-accent); }
/* Fokusringen (focus:ring-<språkfarge>-500) viser seg ved museklikk, der
   :focus-visible ikkje alltid slår til. applyTheme rører han ikkje. */
html[data-profil="v33"] body #curriculum-selector:focus { --tw-ring-color: var(--pt-accent); }
html[data-profil="v33"] body #offline-download-section .bg-red-100 { background-color: var(--pt-tint); }
html[data-profil="v33"] body :is(#offline-download-section, main .max-w-3xl > div > .mb-12) > h2.border-red-500 { border-color: var(--pt-accent); }
html[data-profil="v33"] body #main-bottom-nav .text-red-600 { color: var(--pt-link); }
/* Verktøykorta (createToolCard): sirkel, pil og ring følgjer temafargen */
html[data-profil="v33"] body a[class~="hover:ring-red-500"] .bg-red-500 { background-color: var(--pt-primary); color: var(--pt-on-primary); }
html[data-profil="v33"] body a[class~="hover:ring-red-500"] .text-red-500 { color: var(--pt-link); }
:where(html[data-profil="v33"] body) [class*="hover:ring-"]:hover { --tw-ring-color: var(--pt-accent); }

/* Reflow på 320 px i knutepunkta: lange leksjonstitlar, verktøykorta,
   dagspoenga og vekekalenderen skuva sida 35–69 px breiare. */
html[data-profil="v33"] body :is(.leksjon-link, a[class*="hover:ring-"]) .flex.items-center.gap-4 > :is(.flex-grow, div:not([class])) { min-width: 0; }
/* Leksjons- og verktøykorta: teksten står i ein smal kolonne på 320 px; eit ord som
   er lengre enn kolonnen, blir delt, og framdriftsikona brytast til to rader. */
html[data-profil="v33"] body :is(.leksjon-link, a[class*="hover:ring-"]) .flex.items-center.gap-4 > :is(.flex-grow, div:not([class])) { overflow-wrap: break-word; }
html[data-profil="v33"] body .leksjon-link .progress-icons-mobile { flex-wrap: wrap; }
/* Leksjonskorta under 480 px: talsirkelen og pila på første rad, tittel,
   skildring og framdriftsikona i heile kortbreidda under. Ved sida av
   sirkelen var tekstkolonnen 113 px på 320 px: «Überraschungsparty!» (222 px)
   og «familiemedlemmene» vart delte midt i ordet, og dei fire ikona brotna
   3 + 1. Tekstkolonnen blir display: contents, så barna blir rutenettbarn. */
@media (max-width: 479.98px) {
  html[data-profil="v33"] body :is(.leksjon-link, .leksjon-locked) { padding: 1.25rem; }
  html[data-profil="v33"] body :is(.leksjon-link, .leksjon-locked) > .flex.items-center.gap-4 {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    column-gap: 0.75rem;
    row-gap: 0.25rem;
  }
  html[data-profil="v33"] body :is(.leksjon-link, .leksjon-locked) > .flex.items-center.gap-4 > .flex-grow { display: contents; }
  html[data-profil="v33"] body :is(.leksjon-link, .leksjon-locked) > .flex.items-center.gap-4 > :first-child { grid-area: 1 / 1; }
  html[data-profil="v33"] body :is(.leksjon-link, .leksjon-locked) > .flex.items-center.gap-4 > .ml-auto { grid-area: 1 / 3; }
  html[data-profil="v33"] body :is(.leksjon-link, .leksjon-locked) > .flex.items-center.gap-4 > .flex-grow > * { grid-column: 1 / -1; min-width: 0; }
  html[data-profil="v33"] body :is(.leksjon-link, .leksjon-locked) h3 { margin-top: 0.5rem; }
}
html[data-profil="v33"] body #fremgang-content .flex.gap-4.text-sm { flex-wrap: wrap; }
html[data-profil="v33"] body #fremgang-content .flex.items-center.justify-between { flex-wrap: wrap; column-gap: 0.75rem; }
/* «Ord du kan»-kortet er ei lenkje med tekstlinjer under kvarandre (same grunn). */
html[data-profil="v33"] body #fremgang-content > div > .grid > a[href] { display: block; }
/* Tal-rutenetta: «Grammatikkpoeng» og «Læringsbunken» er eitt ord kvar og
   fekk ikkje plass i tre (to) kolonnar. Kolonnane brytast heller enn orda. */
html[data-profil="v33"] body #fremgang-content .grid.grid-cols-3.gap-4.text-center,
html[data-profil="v33"] body #fremgang-content > div > .grid.grid-cols-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr)); }
html[data-profil="v33"] body #week-calendar-grid > * { flex: 1 1 0; min-width: 0; }
html[data-profil="v33"] body #week-calendar-grid .w-10.h-10 { width: 100%; max-width: 2.5rem; height: auto; aspect-ratio: 1; }
/* «Læringspoeng i dag» (finpussen 14.10, punkt 4, og fase 7 S3): sporet (bg-amber-100 → tint)
   hadde same farge som kortet (gradient → tint), så på 0 poeng fanst inga line. Kanten er
   felttokenet: den sterke kantfargen hadde 2,85:1 mot kortet i mørk modus, felttokenet 3:1. */
html[data-profil="v33"] body #fremgang-content .h-3.rounded-full.overflow-hidden {
  background-color: var(--pt-surface);
  box-shadow: inset 0 0 0 1px var(--pt-field-border);
}
/* Sky-pillen (finpussen 14.10, punkt 1; #auth-container, fixed top-4 right-4) låg oppå
   tittelen i fanene Fremgang, Rangliste og Profil under 768 px. Knutepunktet reserverer
   plassen med mt-20 på headeren (shell.js); fanene hadde ingen. */
@media (max-width: 767.98px) {
  html[data-profil="v33"] body :is(#tab-fremgang, #tab-rangliste, #tab-profil) { padding-top: 3.5rem; }
}
/* Testsida: tittel og «Spørsmål 1 / 10» bryt til to liner når det er trongt. */
html[data-profil="v33"] body #question-view > .flex.justify-between { flex-wrap: wrap; column-gap: 1rem; }
/* Spesialteikna under utfyllingsfeltet (ui.js createSpecialCharsComponent):
   44 px-knappane fekk ikkje plass på éi rad på 320 px (27 px for brei). */
html[data-profil="v33"] body #test-special-chars { flex-wrap: wrap; }
/* Spørsmålet på testsida er brødteksten der (text-xl gav linjehøgd 1,4). */
html[data-profil="v33"] body #question-area > p { line-height: 1.5; }

/* ── Fase 3: modalar og toastar med inline-fargar (krokane står i
   tests/unit/papertek-profil-krokar.test.js). !important berre der fargen
   står inline i elementet; utmerkingsmodalen og poengtoasten sine
   klassefargar blir tatt av spesifisiteten åleine. ── */
/* «Hva er nytt?» (utils/service-worker-manager.js) */
html[data-profil="v33"] body [data-hva-er-nytt] [role="dialog"] { background-color: var(--pt-surface) !important; color: var(--pt-ink) !important; }
html[data-profil="v33"] body [data-hva-er-nytt] #hva-er-nytt-tittel { color: var(--pt-heading) !important; }
html[data-profil="v33"] body [data-hva-er-nytt] [role="dialog"] > p,
html[data-profil="v33"] body [data-hva-er-nytt] [data-hva-er-nytt-lukk] { color: var(--pt-ink-secondary) !important; }
html[data-profil="v33"] body [data-hva-er-nytt] [role="dialog"] > ul { color: var(--pt-ink) !important; }
html[data-profil="v33"] body [data-hva-er-nytt] [data-hva-er-nytt-ok] { background-color: var(--pt-primary) !important; color: var(--pt-on-primary) !important; }
/* «Hva er nytt? 🎉» (finpussen 14.10, punkt 7): 1,5rem er 27 px med profilen (18 px rot), og
   🎉 vippa åleine ned på neste line. 1,25rem (22,5 px) held tittelen på éi line. */
@media (max-width: 479.98px) {
  html[data-profil="v33"] body [data-hva-er-nytt] #hva-er-nytt-tittel { font-size: 1.25rem !important; line-height: 1.75rem !important; }
}
/* Oppdateringsvarselet (utils/sw-oppdatering.js). På 320 px var varselet 229 px breitt, og
   «Oppdater» krympa til 44 px så teksten flaut over i «Lukk» («OppdaterLukk»). Varselet tek
   breidda innhaldet treng (opp til skjermen minus marg), knappane krympar ikkje, og linja
   brytast: på smale skjermar står meldinga åleine og knappane under. */
html[data-profil="v33"] body [data-sw-varsel] { background-color: var(--pt-panel) !important; color: var(--pt-on-panel) !important; width: max-content; max-width: calc(100% - 2rem); flex-wrap: wrap; column-gap: 1rem; row-gap: 0.25rem; }
html[data-profil="v33"] body [data-sw-varsel] [data-sw-oppdater] { color: var(--pt-lime) !important; }
html[data-profil="v33"] body [data-sw-varsel] [data-sw-lukk] { color: var(--pt-on-panel) !important; }
html[data-profil="v33"] body [data-sw-varsel] > :is([data-sw-oppdater], [data-sw-lukk]) { flex-shrink: 0; padding-inline: 0.25rem; }
@media (max-width: 479.98px) {
  html[data-profil="v33"] body [data-sw-varsel] > :first-child { flex-basis: 100%; }
}
/* Poengtoasten (progress/grammar-points.js): profilflate, poenga i lime (Geir 14.10).
   Verbtoasten har gradienten inline, difor !important på bakgrunnen. */
html[data-profil="v33"] body .gp-toast-inner { background: var(--pt-panel) !important; color: var(--pt-on-panel); box-shadow: 0 8px 24px rgba(6, 43, 48, 0.35); }
html[data-profil="v33"] body .gp-toast-count { color: var(--pt-lime); }
/* Poengtoasten (finpussen 14.10, punkt 2; top: 16px, midtstilt) dekte sky-pillen under
   768 px: han står under pillen i staden. Med botnmeny flyttar fase 7 S1 han ned (seinare). */
@media (max-width: 767.98px) {
  html[data-profil="v33"] body .gp-toast { top: 5.25rem; }
}
/* Utmerkingsmodalen (progress/celebrations.js): lime i staden for farge per merke */
html[data-profil="v33"] body #achievement-modal-backdrop .border-l-4 { background-color: var(--pt-tint); border-color: var(--pt-lime); }
html[data-profil="v33"] body #achievement-modal-backdrop h3 { color: var(--pt-heading); }
/* Ikonet står i fargen til blyanten, same klasse og same omfarging som i
   leksjonslista (achievements.js getAchievementColor). Tittelen seier «Den
   grønne blyanten er din!»; eit ikon i overskriftsfargen sa noko anna. */
html[data-profil="v33"] body #achievement-modal-backdrop .achievement-modal-ok { background-color: var(--pt-lime); color: var(--pt-on-lime); border-color: var(--pt-lime); }
/* Blyantar og stjerner: kvart nivå sin farge (krok frå getAchievementColor og
   ikonet i utmerkingsmodalen). Profilen gjorde text-blue-600 og text-amber-500
   begge til lenkjefargen, så blåblyanten og gullblyanten var like. !important
   og plassen etter omfarginga for spansk og fransk: shell.js applyTheme og
   profilen sjølv set text-amber-500 med !important (same tyngd). */
html[data-profil="v33"] body .pt-niva-1 { color: var(--pt-blyant-gronn) !important; }
html[data-profil="v33"] body .pt-niva-2 { color: var(--pt-blyant-bla) !important; }
html[data-profil="v33"] body .pt-niva-3 { color: var(--pt-blyant-rubin) !important; }
html[data-profil="v33"] body .pt-niva-4 { color: var(--pt-blyant-gull) !important; }
/* Eksport- og slettetoast (auth/firebase-feide-auth.js) */
html[data-profil="v33"] body [data-pt-toast] { background: var(--pt-panel) !important; color: var(--pt-on-panel) !important; font-family: var(--pt-font) !important; }
/* Innlogginga på smale skjermar (finpussen 14.10, punkt 5): «Logg inn med Google» braut over
   to liner med ikonet åleine til venstre. Målt på 320 px: tekst, ikon og mellomrom treng
   214 px, knappen hadde 208. Mindre luft rundt, ikkje mindre tekst. */
@media (max-width: 479.98px) {
  html[data-profil="v33"] body [aria-labelledby="auth-login-modal-title"] { padding: 1rem; }
  html[data-profil="v33"] body [aria-labelledby="auth-login-modal-title"] > div { padding: 1rem; }
  html[data-profil="v33"] body [data-provider-buttons] > button { padding-inline: 0.5rem; }
}
/* Mørk modus (finpussen 14.10, punkt 3 og 9): modalboksen og poengtoasten hadde nesten same
   farge som sida under, og ingen kant. Ein tynn ring i den sterke kantfargen. Står etter
   grunnregelen for .gp-toast-inner (same tyngd: rekkjefølgja avgjer box-shadow). */
@media (prefers-color-scheme: dark) {
  html[data-profil="v33"]:where(:not([data-tema="lys"])) body :is(.fixed.inset-0 > :is(.bg-white, [role="dialog"]), [data-hva-er-nytt] > [role="dialog"]) {
    box-shadow: 0 0 0 1px var(--pt-border-strong), 0 25px 50px -12px rgba(0, 0, 0, 0.5) !important;
  }
  html[data-profil="v33"]:where(:not([data-tema="lys"])) body .gp-toast-inner { box-shadow: 0 0 0 1px var(--pt-border-strong), 0 8px 24px rgba(0, 0, 0, 0.5); }
}
/* «Mørk» valt i Profil: same ring som over (sjå tokenblokka øvst). */
html[data-profil="v33"]:where([data-tema="mork"]) body :is(.fixed.inset-0 > :is(.bg-white, [role="dialog"]), [data-hva-er-nytt] > [role="dialog"]) {
  box-shadow: 0 0 0 1px var(--pt-border-strong), 0 25px 50px -12px rgba(0, 0, 0, 0.5) !important;
}
html[data-profil="v33"]:where([data-tema="mork"]) body .gp-toast-inner { box-shadow: 0 0 0 1px var(--pt-border-strong), 0 8px 24px rgba(0, 0, 0, 0.5); }

/* ── Fase 4: Ordtrenar (ordtrener/**, trenarane, gloseprøva, bli-med) ──────── */
/* Fargeklassar Ordtrenaren brukar og leksjonane ikkje (klassedekninga). */
:where(html[data-profil="v33"] body) :is(.bg-blue-800, .bg-sky-700) { background-color: var(--pt-primary); color: var(--pt-on-primary); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-sky-700:hover) { background-color: var(--pt-primary); color: var(--pt-on-primary); }
:where(html[data-profil="v33"] body) :is(.bg-orange-300, .bg-purple-300) { background-color: var(--pt-border); }
:where(html[data-profil="v33"] body) :is(.bg-red-700) { background-color: var(--pt-negative); color: var(--pt-bg); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-gray-50:hover) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-orange-100:hover) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-purple-200:hover) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.hover\:bg-sky-50:hover) { background-color: var(--pt-tint); }
:where(html[data-profil="v33"] body) :is(.focus\:ring-sky-200:focus) { --tw-ring-color: var(--pt-accent); }
:where(html[data-profil="v33"] body) :is(.text-amber-900\/40) { color: var(--pt-ink-secondary); }
:where(html[data-profil="v33"] body) :is(.text-cyan-600, .text-sky-400, .text-lime-700) { color: var(--pt-link); }
:where(html[data-profil="v33"] body) :is(.text-green-300) { color: var(--pt-positive); }
/* Språkfargane i <style> på Ordtrenar-sidene ([data-language="spanish"] …
   !important): ingen språkfargar under profilen (eigarregel 13.10). */
html[data-profil="v33"] body[data-language] :is(.text-sky-400, .text-sky-500, .text-sky-600, .text-sky-700, .text-sky-800) { color: var(--pt-link) !important; }
html[data-profil="v33"] body[data-language] :is(.bg-sky-50, .bg-sky-100) { background-color: var(--pt-tint) !important; }
/* …men ikkje der flata er ikonet si eiga (data-pt-ikonkort): den lyse ikonfila skal liggje på --pt-surface
   (kapittelboblene i Ordtrenaren med PaperTek-hengelåsen, 20.10.2026). */
html[data-profil="v33"] body[data-language] [data-pt-ikonkort]:is(.bg-sky-50, .bg-sky-100) { background-color: var(--pt-surface) !important; }
html[data-profil="v33"] body[data-language] :is(.bg-sky-500, .bg-sky-600) { background-color: var(--pt-primary) !important; color: var(--pt-on-primary) !important; }
html[data-profil="v33"] body[data-language] :is(.border-sky-100, .border-sky-200) { border-color: var(--pt-border) !important; }
html[data-profil="v33"] body[data-language] :is(.border-sky-500) { border-color: var(--pt-accent) !important; }
html[data-profil="v33"] body[data-language] .shadow-sky-200 { --tw-shadow-color: color-mix(in srgb, var(--pt-heading) 15%, transparent) !important; box-shadow: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -1px var(--tw-shadow-color) !important; }
/* Kombiner-brikkene (match.js) set tilstanden med INLINE stil: vald = amber-100
   (#fef3c7), rett par = green-200, gale par = red-200, med fast mørk tekstfarge på
   dei to siste. Vald brikke arvar lys tekst i mørk modus og stod på 1,03:1, og
   rett/gale var berre fargar utan eigen farge frå profilen. Ein inline stil slår berre
   !important, så desse reglane har det (ID + klassar gjev òg høgare tyngd enn
   .bg-white-regelen). Rett og gale får ✓ og ✗ som ::after, som verbknappane over. */
html[data-profil="v33"] body #kombiner-grid button.selected { background-color: var(--pt-lime-mark) !important; border-color: var(--pt-heading) !important; color: var(--pt-ink); }
html[data-profil="v33"] body #kombiner-grid button.correct { background-color: var(--pt-positive-bg) !important; border-color: var(--pt-positive) !important; color: var(--pt-positive) !important; }
html[data-profil="v33"] body #kombiner-grid button.incorrect { background-color: var(--pt-negative-bg) !important; border-color: var(--pt-negative) !important; color: var(--pt-negative) !important; }
html[data-profil="v33"] body #kombiner-grid button.correct::after { content: " ✓"; font-weight: 700; }
html[data-profil="v33"] body #kombiner-grid button.incorrect::after { content: " ✗"; font-weight: 700; }

/* Modusikon: éin felles utsjånad (eigar 16.10). Språkregelen for text-sky-600
   og dei andre har spesifisitet (0,3,2) og står tidlegare i fila. Éin attributt
   her gjev òg (0,2,2), og då vinn språkfargen: ikonet fekk --pt-link i staden
   for --pt-accent på tysk, spansk, international og index. [data-pt-modusikon]
   to gonger gjev (0,3,2), og regelen står etter språkreglane, så han vinn
   tie-breaken. Ikkje gjer éin attributt av det igjen.
   Ikonbytet (19.10, spesifikasjon 2026-10-19-ikonbytte §6.4): designprofil-ikonet står rett på
   kortet (kortet er --pt-surface via data-pt-ikonkort), aldri på ei plate, så plata er gjennomsiktig
   og boksen tek storleiken til ikonet (64 px, prøve-radene 48 px) i staden for w-11/w-12.
   Glyffargen gjeld det gamle ikonet, som er skjult under v33. */
html[data-profil="v33"] body [data-pt-modusikon][data-pt-modusikon] { background-color: transparent !important; color: var(--pt-accent) !important; width: auto; height: auto; border-radius: 0; }
/* Ordklassemerke: ingen !important-regel i profilen rører fargeklassane
   (text-amber-700 osv.), så vanleg spesifisitet held. */
html[data-profil="v33"] body [data-pt-ordklasse] { background-color: var(--pt-tint); color: var(--pt-ink); border-color: var(--pt-border-strong); }

/* Tilbakelenkja øvst på Ordtrenar-sidene er 42 px høg (py-2 + tekst-sm):
   under målet på 44 px. Ingen !important: Tailwind sett ingen min-height. */
html[data-profil="v33"] body a.block.px-5.py-2 { min-height: 44px; }
/* «Enkelt»/«Vanskelig»/«Behald»-undertekstene på flashcard-knappane (òg «Øv på glosene» i leksjonane) er
   opacity-60: fargen på knappen blir for svak mot flata. Full dekning gjev
   kontrasten; storleiken (text-xs) skil dei frå knappeteksten. Ingen !important:
   .opacity-60 har lågare spesifisitet enn denne. */
html[data-profil="v33"] body button span.text-xs.font-normal.opacity-60 { opacity: 1; }

/* 320 px: 18 px tekst gjer pillane i statuslinja og toppraden i ordkortet for
   breie, så den siste pillen blei avkutta ved høgre kant (body har overflow-hidden,
   så ingen sideveis rulling synleg). Radene får bryte; ml-auto held poengpillen til høgre.
   Ordkorttoppen har tre barn (teljar, mestringspille, knappar) og same fiks. Verbtrenaren
   sitt startkort er ein flex-ting med min-width: auto og vart 386 px i staden for 320. */
:where(html[data-profil="v33"] body) #view-dashboard > .flex.px-5.pt-4 { flex-wrap: wrap; row-gap: 0.5rem; }
:where(html[data-profil="v33"] body) #vocab-exercise-area .flex.justify-between.items-center.border-b.pb-4.z-20 { flex-wrap: wrap; gap: 0.5rem; }
/* Berre min-width: 0 — max-width: 100 % (ID-tyngd) slo max-w-*-taka på kortet og
   gjorde trenarkorta fullbreie på store skjermar (sluttgjennomgangen: skriv 672 → 1244 px). */
:where(html[data-profil="v33"] body) #vocab-exercise-area > * { min-width: 0; }
/* Ordet på ordkortet er text-5xl (3 rem = 54 px under rota på 112,5 %), med black-skrift.
   På 320 px er kortflata 226 px brei: «Deutschland» og «¡Bienvenido!» gjekk frå kant til
   kant, og eit lengre ord (revisjonen set inn «Geburtstagsgeschenk») rakk 443 px. Ordet
   krympar med skjermen, ikkje under 2 rem (36 px), og svært lange ord får bryte. Berre
   under md (≥ 768 px har sida text-6xl og plass). */
@media (max-width: 767px) {
  :where(html[data-profil="v33"] body) #flashcard h2 { font-size: max(2rem, min(3rem, 10vw)); overflow-wrap: anywhere; }
}

/* bli-med (join-group.html, eigen <style>): profilflater og -knappar. Sida
   har sin eigen mørke gradient og oransje knapp; profilen byter dei ut.
   Spesifisiteten (0,3,2 og oppover) slår reglane i sida si <style> utan !important. */
html[data-profil="v33"] body[data-side="bli-med"] { background: var(--pt-bg); color: var(--pt-ink); font-family: var(--pt-font); }
html[data-profil="v33"] body[data-side="bli-med"] .card { background: var(--pt-surface); border: 1px solid var(--pt-border); }
html[data-profil="v33"] body[data-side="bli-med"] :is(p.lede, .code-label, .footer) { color: var(--pt-ink-secondary); }
html[data-profil="v33"] body[data-side="bli-med"] .footer a { color: var(--pt-link); }
html[data-profil="v33"] body[data-side="bli-med"] .code-block { background: var(--pt-tint); }
html[data-profil="v33"] body[data-side="bli-med"] .button.primary { background: var(--pt-primary); color: var(--pt-on-primary); }
html[data-profil="v33"] body[data-side="bli-med"] .button.secondary { background: var(--pt-surface-soft); color: var(--pt-ink); border-color: var(--pt-border-strong); }
/* Brødtekst 18 px: 1rem er 18 px under rota på 112,5 % (fase 7, T10; her stod 1,125rem = 20,25 px
   med ein kommentar som trudde 1rem var 16 px). Sida si eiga <style> har 16 px. */
html[data-profil="v33"] body[data-side="bli-med"] p.lede { font-size: 1rem; line-height: 1.6; }

/* ── Fase 5: Konkurranse (/k/ elevsida, /k/vis/ projektoren) ───────────────── */
/* Tre fargeklassar Konkurranse brukar og leksjonane ikkje (klassedekninga):
   valt svarknapp (ring-sky-500), tekst på podiet (text-amber-950) og det gale
   skrivesvaret (text-red-900, lagt til av elev-visning.js). */
:where(html[data-profil="v33"] body) :is(.ring-sky-500) { --tw-ring-color: var(--pt-accent); }
:where(html[data-profil="v33"] body) :is(.text-amber-950) { color: var(--pt-heading); }
:where(html[data-profil="v33"] body) :is(.text-red-900) { color: var(--pt-negative); }
/* Førsteplassen får Soft Lime med mørk tekst (--pt-on-lime er lik i lys og mørk).
   Kroken data-pt-forsteplass står på podieblokka, toppliste-raden og plasstalet
   til eleven. Ingen farge per plass: andre- og tredjeplass på podiet får vanleg
   flate (.bg-amber-400 er elles lime i leksjonane). Kanten går heilt rundt (fase 7, K4:
   utan nedkant såg blokkene ut som opne boksar mot den lyse bakgrunnen). */
html[data-profil="v33"] body [data-pt-forsteplass] { background-color: var(--pt-lime); color: var(--pt-on-lime); }
html[data-profil="v33"] body [data-testid^="pall-"] .bg-amber-400:not([data-pt-forsteplass]) { background-color: var(--pt-tint); color: var(--pt-heading); border: 1px solid var(--pt-border-strong); }
/* Plasstalet til eleven er eit frittståande avsnitt: lime-flata treng luft og runde hjørne. */
html[data-profil="v33"] body p[data-pt-forsteplass] { border-radius: 1rem; padding: 0.25rem 1rem; }
/* Raden i lista: same luft som flata, teksta arvar on-lime. */
html[data-profil="v33"] body li[data-pt-forsteplass] { border-radius: 0.75rem; }
/* Eleven si toppliste har ingen sidepolstring, så teksten rørte lime-kanten. Utan
   spesifisitet (:where), så px-5 på projektorlista (1,25rem) står. */
:where(html[data-profil="v33"] body li[data-pt-forsteplass]) { padding-inline: 0.75rem; }

/* Revisjonsfunn, elevsida (/k/): hovudraden (flagg, kallenamn, konto, poengsum)
   ligg på éi flex-linje. På 320 px rakk ikkje «N riktige» innanfor skjermen og sida
   fekk sideveis rulling; no bryt raden, og eit langt kallenamn kan krympe og brytast. */
html[data-profil="v33"] body #konk-hovud { flex-wrap: wrap; row-gap: 0.25rem; }
html[data-profil="v33"] body #konk-hovud [data-testid="kallenamn"] { min-width: 0; overflow-wrap: anywhere; }

/* Revisjonsfunn, projektoren (/k/vis/). Tala er store på prosjektor og skal vere det;
   på smal skjerm (ikkje bruksområdet, men revisjonen krev det) følgjer dei breidda.
   Ingen max-width: 100% på containerar (fase 4: Tailwind max-w-* brest). */
/* Koden: text-8xl (6rem) held seg på brei skjerm; 15vw er mindre først under 640 px. */
html[data-profil="v33"] body #konk-projektor [data-testid="kode"] { font-size: min(6rem, 15vw); overflow-wrap: anywhere; }
html[data-profil="v33"] body #konk-projektor [data-testid="adresse"] { overflow-wrap: anywhere; }
/* Spelarantalet i lobbyen er brødtekst: linjehøgd 1,5 (text-3xl gav 1,2). Den ekstra
   luft (1,5em mot 2,25rem, 10 px) flytta lobbylista og knappane ned (fase 7, K8): marga
   tek henne att på kvar side, så lina tek same plass som før og ingenting under flyttar seg. */
html[data-profil="v33"] body #konk-projektor [data-testid="antal"] { line-height: 1.5; margin-top: calc((2.25rem - 1.5em) / 2); margin-bottom: calc(1rem + (2.25rem - 1.5em) / 2); }
/* Podiet: kolonnene (w-56) får krympe under innhaldsbreidda, og namn og poeng brytast. */
html[data-profil="v33"] body #konk-projektor [data-testid="pall"] { min-width: 0; }
html[data-profil="v33"] body #konk-projektor [data-testid^="pall-"] { min-width: 0; }
html[data-profil="v33"] body #konk-projektor [data-testid^="pall-"] > span { overflow-wrap: anywhere; max-width: 100%; }
/* «Tilbake til gloseprøvene»: berøringsmål minst 44 px (var 32). */
html[data-profil="v33"] body #konk-projektor [data-testid="til-gloseprovene"] { padding-block: 0.625rem; min-height: 44px; }

/* Revisjonsfunn, «Ny konkurranse»/«Ny runde» (#konk-opprett-modal, opprett.js). Overlegget
   er flex med items-center og overflow-y-auto. Med 18 px tekst blir kortet høgare enn
   ein telefon (821 px), og då klippar sentreringa toppen over kanten der ingen rulling
   når han (topp −127 px på 320×568). Toppjuster overlegget og la kortet sentrere seg
   sjølv med auto-marg: eit lågt kort står framleis midt på skjermen, eit høgt kort
   byrjar øvst og rullar. Ikkje «safe center» (eldre Safari). Auto-marga slår my-8. */
html[data-profil="v33"] body #konk-opprett-modal { align-items: flex-start; }
html[data-profil="v33"] body #konk-opprett-modal > div { margin-block: auto; }

/* Ordkortet (elev-visning.js KORT) fekk ein farge per språk: tysk amber, fransk blå og
   spansk RAUD, og raudt er profilens farge for eit galt svar. Eigaravgjerd: ingen farge
   per språk. Same kort i alle språk (tint-flate, aksentkant, overskriftstekst); flagget
   i hjørnet og retningsstripa fortel framleis kva språk ordet står på. */
html[data-profil="v33"] body [data-testid="ordkort"] { background-color: var(--pt-tint); border-color: var(--pt-accent); color: var(--pt-heading); }

/* Hovudknappane på projektoren (Start, Ny runde, Vis pallen, Bytt konto, projektor.js)
   og innloggingsknappen (bytt-konto.js) er bg-green-600, og grøn er statusfargen for
   «rett». Statusfargar høyrer berre til rett/gale og klokka; ein handlingsknapp er
   primærfargen, som knappane elles i profilen. Hover står i ein eigen regel. */
html[data-profil="v33"] body #konk-projektor .bg-green-600 { background-color: var(--pt-primary); color: var(--pt-on-primary); }
html[data-profil="v33"] body #konk-projektor .hover\:bg-green-700:hover { background-color: var(--pt-primary); color: var(--pt-on-primary); }

/* Sifra i Atkinson er proporsjonale, så klokka og poenga flimrar breidda for kvart
   tikk. Tabulære siffer held breidda stø. Elevklokka (tid), poengsummen i hovudraden,
   elevens nedteljing og projektorens nedteljing og framdrift (tid att / ferdige). */
html[data-profil="v33"] body [data-testid="tid"],
html[data-profil="v33"] body #konk-score,
html[data-profil="v33"] body [data-testid="nedteljing"],
html[data-profil="v33"] body [data-testid="framdrift"] { font-variant-numeric: tabular-nums; }

/* ── Fase 6: lærar og info (lærarvisingane, presentasjonsvisaren, infosidene) ── */
/* Seks fargeklassar lærarkoden brukar og leksjonane ikkje (klassedekninga). Alle sit på
   mørke flater: teorirutene i presentasjonsvisaren (bg-stone-900 på <body>, bg-amber-900
   på ordkortet si bakside og fun fact-boksen) og «Logg inn med Apple»-knappen
   (proveperiode.html, bg-stone-900 med kvit tekst). Ei mørk flate er spelpanelet, og
   teksten på han er on-panel, same rolle som bg-stone-800 (.bg-stone-700/800 over).
   Visaren held lys palett (data-tema-fast="lys"), og panelet er då den same mørke
   teal-flata i både lys og mørk modus. */
:where(html[data-profil="v33"] body) :is(.bg-stone-900, .bg-amber-900) { background-color: var(--pt-panel); color: var(--pt-on-panel); }
:where(html[data-profil="v33"] body) :is(.text-stone-100, .text-stone-200, .text-amber-200) { color: var(--pt-on-panel); }
/* «Logg inn med Apple» (proveperiode.html) står på eit kort (bg-white = --pt-surface). I mørk
   modus er panelet og kortet same farge (#0B3E44), og knappen hadde inga synleg flate. Ein kant
   i den sterke kantfargen (≥ 3:1 mot kortet i begge paletter) viser knappen i begge modusar;
   i lys modus står kanten rundt ei mørk flate og endrar lite. hover:bg-black (svart, utanfor
   paletten) blir panelet, og kanten får aksentfargen som peikarrespons. */
html[data-profil="v33"] body[data-side="proveperiode"] button.bg-stone-900 { border: 1px solid var(--pt-border-strong); }
html[data-profil="v33"] body[data-side="proveperiode"] button.hover\:bg-black:hover { background-color: var(--pt-panel); border-color: var(--pt-accent); }
/* Fokusringen på felta i proveperiode.html: aksentfargen, som dei andre ringane. */
:where(html[data-profil="v33"] body) :is(.focus\:ring-amber-400:focus) { --tw-ring-color: var(--pt-accent); }

/* Dei seks infosidene med eigen <style> (data-side på <body>). Fargeliteralane i sidene
   sine eigne reglar blir erstatta av profilfargar, så lys og mørk palett følgjer med.
   Innhald, rekkjefølgje og synlegheit blir ikkje rørt; skrift, fargar og avstandar blir
   det. Brødtekst minst 18 px: rota er 112,5 %, så 1em og 1rem er 18 px. */
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) {
  background: var(--pt-bg);
  color: var(--pt-ink);
  font-family: var(--pt-font);
  line-height: 1.6;
}
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) h1 { color: var(--pt-heading); border-bottom: 2px solid var(--pt-accent); }
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) :is(h2, h3) { color: var(--pt-heading); }
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) a { color: var(--pt-link); }
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) .last-updated { color: var(--pt-ink-secondary); font-size: 1em; } /* 0,9em gav 16,2 px */
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) :is(.contact, .summary) { background: var(--pt-tint); color: var(--pt-ink); border-color: var(--pt-accent); }
html[data-profil="v33"] body[data-side="support"] .faq-item h3 { color: var(--pt-heading); }
/* Tabellane (tilgjengelegheit, samsvar): flate, kantlinjer og overskriftsrad.
   Skriftstorleiken var 0,92em og 0,875em, under 18 px. På samsvarssida gjeld 18 px berre
   på skjerm: sida har eigne utskriftsreglar (table 0,8em, body #fff), og dei skal vinne på
   papir (sjå @media print under). */
html[data-profil="v33"] body:is([data-side="tilgjengelegheit"], [data-side="samsvar"]) table { background: var(--pt-surface); color: var(--pt-ink); }
html[data-profil="v33"] body[data-side="tilgjengelegheit"] table { font-size: 1em; }
@media screen {
  html[data-profil="v33"] body[data-side="samsvar"] table { font-size: 1em; }
}
html[data-profil="v33"] body:is([data-side="tilgjengelegheit"], [data-side="samsvar"]) :is(th, td) { border-color: var(--pt-border); }
html[data-profil="v33"] body:is([data-side="tilgjengelegheit"], [data-side="samsvar"]) th { background: var(--pt-surface-soft); color: var(--pt-heading); }
html[data-profil="v33"] body[data-side="samsvar"] tr:nth-child(even) td { background: var(--pt-surface-soft); }
/* Inline-stil i sidene (<p style="color:#666; font-size:0.9em"> nederst i tilgjengelegheits-
   erklæringa, <hr style="border-top:… #ddd">): !important slår inline-stilen. */
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) p[style] { color: var(--pt-ink-secondary) !important; font-size: 1em !important; }
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"]) hr[style] { border-top-color: var(--pt-border) !important; }
/* Status i tilgjengelegheitserklæringa: teksten står alltid ved sida av fargen. */
html[data-profil="v33"] body[data-side="tilgjengelegheit"] .status-ok { color: var(--pt-positive); }
html[data-profil="v33"] body[data-side="tilgjengelegheit"] .status-partial { color: var(--pt-warning-ink); }
html[data-profil="v33"] body[data-side="tilgjengelegheit"] .status-fail { color: var(--pt-negative); }
/* Samsvarssida: dokumentkort, merknad og utskriftsknapp. */
html[data-profil="v33"] body[data-side="samsvar"] .document-card { background: var(--pt-surface); border-color: var(--pt-border); color: var(--pt-ink); }
html[data-profil="v33"] body[data-side="samsvar"] .document-card h3 { color: var(--pt-heading); border-bottom-color: var(--pt-border); }
html[data-profil="v33"] body[data-side="samsvar"] .document-card p { color: var(--pt-ink); }
html[data-profil="v33"] body[data-side="samsvar"] .document-card .note { background: var(--pt-tint); color: var(--pt-ink); border-left-color: var(--pt-accent); font-size: 1em; }
html[data-profil="v33"] body[data-side="samsvar"] .section-inline h4 { color: var(--pt-ink-secondary); }
html[data-profil="v33"] body[data-side="samsvar"] .print-btn { background: none; border-color: var(--pt-accent); color: var(--pt-link); font-size: 1em; min-height: 44px; }
html[data-profil="v33"] body[data-side="samsvar"] .print-btn:hover { background-color: var(--pt-tint); }
/* Utskrift av samsvarssida: sida sin eigen utskriftsregel set body til kvitt (#fff), men
   kroppsreglane over (og fase 3) er sterkare enn han. --pt-surface er kvitt i den lyse
   paletten som print alltid brukar (tokenblokka øvst), så papiret blir som sida vil. */
@media print {
  html[data-profil="v33"] body[data-side="samsvar"] { background: var(--pt-surface); }
}
/* 404-sida: standardsida frå Firebase, med px-storleikar og eigne fargar i #message. */
html[data-profil="v33"] body[data-side="404"] { background: var(--pt-bg); color: var(--pt-ink); font-family: var(--pt-font); }
html[data-profil="v33"] body[data-side="404"] #message { background: var(--pt-surface); color: var(--pt-ink); box-shadow: none; border: 1px solid var(--pt-border); }
html[data-profil="v33"] body[data-side="404"] #message :is(h1, h2) { color: var(--pt-heading); font-weight: 700; }
html[data-profil="v33"] body[data-side="404"] #message h1 { font-size: 1.5rem; }
html[data-profil="v33"] body[data-side="404"] #message h2 { font-size: 1.125rem; }
html[data-profil="v33"] body[data-side="404"] #message h3 { color: var(--pt-ink-secondary); font-weight: 700; font-size: 1rem; }
html[data-profil="v33"] body[data-side="404"] #message p { font-size: 1rem; line-height: 1.6; }
html[data-profil="v33"] body[data-side="404"] #message a { background: var(--pt-primary); color: var(--pt-on-primary); box-shadow: none; }
html[data-profil="v33"] body[data-side="404"] #load { color: var(--pt-ink-secondary); }
@media (max-width: 600px) {
  html[data-profil="v33"] body[data-side="404"] { border-top-color: var(--pt-accent); }
  html[data-profil="v33"] body[data-side="404"] #message { background: var(--pt-bg); border: 0; }
}

/* ── Lærarmodus i hovudappen (Rangliste: klasser, klassedetalj, gloseprøver) ── */
/* Brødteksten (text-sm/text-xs) er 18 px gjennom løftet i 1b, som gjeld lærarar og elevar likt. */

/* Rader i klassedetaljen og prøveresultatet: rang, namn, strek, poeng og knapp på éi linje.
   På 320 px fekk namnet resten (0 px) fordi flex-1 har basis 0: ingenting kunne bryte til
   ei ny linje, og lange namn gjekk ut av skjermen. No bryt rada, namnet får ei heil linje
   (basis 10rem) og blir ikkje avkorta (.truncate gøymde resten av namnet). */
html[data-profil="v33"] body :is(#tcd-content, #tr-content) > .flex.items-center { flex-wrap: wrap; }
html[data-profil="v33"] body :is(#tcd-content, #tr-content) > .flex.items-center > .flex-1.min-w-0 { flex-basis: 10rem; min-width: min(10rem, 100%); }
html[data-profil="v33"] body :is(#tcd-content, #tr-content, #tgo-innhald) .truncate { overflow: visible; text-overflow: clip; white-space: normal; overflow-wrap: anywhere; }
/* Vekeveljaren og knappane under klassestatistikken: på 320 px blei <select id="tcd-week">
   17 px brei og viste berre «De». Raden bryt, og veljaren krympar ikkje (flex-shrink 0): han
   held si eiga breidd, som nettlesaren reknar ut frå det lengste alternativet. Revisjonen
   (selectKlipt) målar at det valde alternativet får plass. */
html[data-profil="v33"] body #tcd-controls { flex-wrap: wrap; }
html[data-profil="v33"] body #tcd-week { flex: 0 0 auto; }
/* Prøvelistene (klassedetaljen og oversynet): tittelen og statusmerket bryt i staden for å gå
   ut av skjermen. */
html[data-profil="v33"] body :is(.tcd-test-row, [data-prove-kode]) .flex.items-center.gap-2 { flex-wrap: wrap; }

/* Toppradene i lærarvisingane (tilbake, tittel, knappar) og kort-toppradene i Rangliste
   (Vennegrupper: Opprett og Bli med) bryt ned på 320 px; knappane har whitespace-nowrap. */
html[data-profil="v33"] body #rangliste-content > .space-y-4 > .flex.items-center.gap-3:first-child { flex-wrap: wrap; }
html[data-profil="v33"] body #rangliste-content > .space-y-4 > .flex.items-center.gap-3:first-child > h2.flex-1 { flex-basis: 8rem; }
html[data-profil="v33"] body #rangliste-content .flex.items-center.justify-between.mb-4 { flex-wrap: wrap; gap: 0.75rem; }

/* Prøveresultatet: bestått og ikkje bestått skal ikkje stå som berre farge og tal. Eit teikn
   etter prosenten (✓ 80 % og over, ~ 50–79 %, ✗ under 50 %), same mønster som rett/gale i
   øvingane. Klasseavsnittet (poenga «659 lp») er ikkje ein karakter og får ikkje teikn.
   Alternativteksten (det skjermlesaren seier) er bokmål som resten av UI-et, og nynorsk når
   UI-språket er nynorsk (body[data-ui-language="nn"]). Den vanlege content-linja først er for
   nettlesarar utan alternativtekst-forma. */
html[data-profil="v33"] body #tr-content .text-green-700.bg-green-50::after { content: " ✓"; content: " ✓" / "høyt resultat"; }
html[data-profil="v33"] body #tr-content .text-orange-700.bg-orange-50::after { content: " ~"; content: " ~" / "middels resultat"; }
html[data-profil="v33"] body #tr-content .text-red-700.bg-red-50::after { content: " ✗"; content: " ✗" / "lavt resultat"; }
html[data-profil="v33"] body[data-ui-language="nn"] #tr-content .text-green-700.bg-green-50::after { content: " ✓"; content: " ✓" / "høgt resultat"; }
html[data-profil="v33"] body[data-ui-language="nn"] #tr-content .text-orange-700.bg-orange-50::after { content: " ~"; content: " ~" / "middels resultat"; }
html[data-profil="v33"] body[data-ui-language="nn"] #tr-content .text-red-700.bg-red-50::after { content: " ✗"; content: " ✗" / "lågt resultat"; }

/* «Opprett gloseprøve» er 817 px høg på 375×667 og 853 på 320×568: med items-center og my-8
   blei toppen og første felt ståande over skjermkanten, utan veg dit. Overlegget byrjar øvst
   og rullar; auto-marga sentrerer kortet når det er plass (som konkurranse-dialogen).
   Ikkje «safe center» (eldre Safari). Auto-marga slår my-8. */
html[data-profil="v33"] body #tcd-create-test-modal { align-items: flex-start; }
html[data-profil="v33"] body #tcd-create-test-modal > div { margin-block: auto; }

/* ── Presentasjonsvisaren (/teacher-presentation-viewer.html) ── */
/* Reglane står under body[data-side="visar"]: berre visaren har den kroken. data-tema-fast="lys"
   (som held paletten lys) deler han med projektoren i Konkurranse (/k/vis), og reglane under skal
   ikkje nå projektoren.
   Visaren held lys palett (data-tema-fast="lys"), men toppfeltet, botnfeltet, tabellane,
   frasane og ordkorta er mørke paneler (bg-stone-700/800, bg-amber-900). <body> har òg
   bg-stone-900, men står ikkje med: scena er lys (sjå under). Tekstfargane i
   profilen er laga for lyse flater: text-stone-300/400/500 blei ink-secondary og
   text-amber-400/500 blei lenkjefargen, begge mørke, og stod då mørkt på panelet
   (1,32:1 på tittelen, 1,45:1 på «Trykk SPACE» og «Lukk»). På eit panel er teksten
   on-panel, og amber-aksenten (tittel og tabelloverskrifter) er lime, same rolle som
   text-amber-300 over. */
html[data-profil="v33"] body[data-side="visar"] :is(.bg-stone-700, .bg-stone-800, .bg-amber-900) :is(.text-stone-300, .text-stone-400, .text-stone-500) { color: var(--pt-on-panel); }
html[data-profil="v33"] body[data-side="visar"] :is(.bg-stone-700, .bg-stone-800, .bg-amber-900) .text-amber-400 { color: var(--pt-lime); }
/* !important slår regelen over for Spansk og fransk (ingen språkfargar), som gjer
   .text-amber-500 til lenkjefargen med !important og elles gjer tittelen mørk på mørkt. */
html[data-profil="v33"] body[data-side="visar"] :is(.bg-stone-700, .bg-stone-800, .bg-amber-900) .text-amber-500 { color: var(--pt-lime) !important; }

/* Scena er lys: <body class="bg-stone-900"> får ikkje panelfargen (panelreglane over gjeld
   etterkomarar av body, ikkje body sjølv), og profilen gjer han til --pt-bg. Tittellysbiletet
   (h1 text-white) og tekstlysbildet (text-stone-200) vart då kvit tekst på lys scene: 1,03:1,
   og tittelen på lysbilde 1 var usynleg. Tekst på scena utanfor panela får ink og heading. */
html[data-profil="v33"] body[data-side="visar"] #slide-container :is(.text-white, .text-stone-100, .text-stone-200):not(:is(.bg-stone-700, .bg-stone-800, .bg-amber-900), :is(.bg-stone-700, .bg-stone-800, .bg-amber-900) *) { color: var(--pt-ink); }
html[data-profil="v33"] body[data-side="visar"] #slide-container h1:is(.text-white):not(:is(.bg-stone-700, .bg-stone-800, .bg-amber-900), :is(.bg-stone-700, .bg-stone-800, .bg-amber-900) *) { color: var(--pt-heading); }

/* Utforming. Toppfeltet bryt ned på smal skjerm (Lukk låg 15 px utanfor kanten på 320 px), og
   lysbildet rullar inni sitt eige felt i staden for å dytte botnfeltet ut av vindauget
   (body er h-screen, og lysbilde 5 er høgare enn 900 px). Lysbildet byrjar øvst og rullar;
   auto-marga sentrerer det når det er plass (ikkje «safe center»: eldre Safari). */
html[data-profil="v33"] body[data-side="visar"] > nav { flex-wrap: wrap; gap: 0.5rem; }
html[data-profil="v33"] body[data-side="visar"] > nav .flex.gap-4 { flex-wrap: wrap; gap: 0.5rem 1rem; }
html[data-profil="v33"] body[data-side="visar"] #pres-title { min-width: 0; overflow-wrap: anywhere; }
html[data-profil="v33"] body[data-side="visar"] #close-btn { min-width: 44px; min-height: 44px; }
html[data-profil="v33"] body[data-side="visar"] #slide-container { min-height: 0; overflow-y: auto; align-items: flex-start; }
html[data-profil="v33"] body[data-side="visar"] #slide-container > * { margin-block: auto; }
/* Tastaturet i visaren: lysbildefeltet får fokus frå skriptet (tabindex="-1", renderSlide), så
   ↓/PageDown rullar eit langt lysbilde. Styrer læraren med tastaturet, skal ho sjå kvar fokuset er
   (Geir 22.10, WCAG 2.4.7): feltet får den doble profilringen lagd innanfor kanten (som gåtene i
   «Fra boka»), sidan ein ring utanfor ville stå mot kanten av vindauget. Med mus eller trykk
   (:focus utan :focus-visible) står det ingen ring på prosjektoren. !important slår
   !important-regelen for :focus-visible i grunnlaget. */
html[data-profil="v33"] body[data-side="visar"] #slide-container:focus:not(:focus-visible) { outline: none !important; box-shadow: none !important; }
html[data-profil="v33"] body[data-side="visar"] #slide-container:focus-visible { outline-offset: -6px !important; box-shadow: inset 0 0 0 3px var(--pt-focus-outer) !important; }
/* Botnfeltet i visaren (Geir 22.10): sporet, fyllet og begge knappane fekk same panelfarge som
   feltet (bg-stone-700/800 og bg-amber-500/600 blir alle --pt-panel), så framdrifta og knappane
   forsvann. Fyllet er lime på eit lyst spor, «Neste» er lime (hovudhandlinga) og «Forrige» har
   ein kvit kant på panelet. Inaktiv knapp held disabled:opacity-50 frå Tailwind. Fyllet er
   bg-amber-500, og !important slår !important-regelen for .bg-amber-500 i knappebolken. */
html[data-profil="v33"] body[data-side="visar"] > footer #progress-bar { background-color: var(--pt-lime) !important; }
html[data-profil="v33"] body[data-side="visar"] > footer :has(> #progress-bar) { background-color: color-mix(in srgb, var(--pt-on-panel) 28%, var(--pt-panel)); }
html[data-profil="v33"] body[data-side="visar"] > footer #next-btn { background-color: var(--pt-lime); color: var(--pt-on-lime); }
html[data-profil="v33"] body[data-side="visar"] > footer #prev-btn { background-color: transparent; color: var(--pt-on-panel); box-shadow: inset 0 0 0 2px var(--pt-on-panel); }
html[data-profil="v33"] body[data-side="visar"] > footer #prev-btn:not(:disabled):hover { background-color: color-mix(in srgb, var(--pt-on-panel) 14%, var(--pt-panel)); }
html[data-profil="v33"] body[data-side="visar"] > footer #next-btn:not(:disabled):hover { background-color: color-mix(in srgb, var(--pt-lime) 85%, var(--pt-on-panel)); }
/* Låge skjermar (1280×800 og 1280×720 er vanlege prosjektorar): dei siste radene på lange
   lysbilde (fraselista i 1.2: 824 px i eit felt på 620) stod under botnfeltet. Lysbildet rullar
   med mus og med ↓/PageDown (fokusregelen over), men ein klikkar kan berre bla, så lysbildet
   skal helst få plass: toppfeltet, botnfeltet og feltet rundt
   lysbildet blir lågare, og skriftstorleikane som står i vw (inline-stil frå visaren, ikkje
   tilpassa høgda) får eit tak i vh. !important slår inline-stilen (style="font-size: clamp(…)",
   margin-bottom og line-height på tittellysbiletet). Ingen tekst går under 18 px (1rem). */
@media (max-height: 860px) {
  html[data-profil="v33"] body[data-side="visar"] > nav { padding-block: 0.5rem; }
  html[data-profil="v33"] body[data-side="visar"] > footer { padding-block: 0.5rem; }
  html[data-profil="v33"] body[data-side="visar"] #slide-container { padding-block: 1rem; }
  /* Overskrifta på lysbildet (clamp(2rem, 4vw, 3.5rem) eller clamp(2.5rem, 5vw, 5rem)). */
  html[data-profil="v33"] body[data-side="visar"] #slide-container h2[style*="font-size"] { font-size: clamp(1.75rem, min(4vw, 6vh), 3.5rem) !important; margin-bottom: 1rem; }
  /* Tittellysbiletet: emoji (clamp(6rem, 15vw, 12rem)), tittel (clamp(3rem, 7vw, 6rem)) og undertittel. */
  html[data-profil="v33"] body[data-side="visar"] #slide-container .slide-enter > div[style*="font-size"]:has(+ h1) { font-size: clamp(3rem, 14vh, 12rem) !important; line-height: 1.2; margin-bottom: 1rem !important; }
  html[data-profil="v33"] body[data-side="visar"] #slide-container .slide-enter > h1[style*="font-size"] { font-size: clamp(2rem, min(7vw, 9vh), 6rem) !important; margin-bottom: 1rem; }
  html[data-profil="v33"] body[data-side="visar"] #slide-container .slide-enter > h1 + p[style*="font-size"] { font-size: clamp(1.25rem, min(3.5vw, 5vh), 3rem) !important; }
  /* Fraselista: frasen (clamp(1.2rem, 2.5vw, 1.75rem)), radene og tolkinga under. */
  html[data-profil="v33"] body[data-side="visar"] #slide-container .border-b.px-8.py-4 { padding-block: 0.5rem; }
  html[data-profil="v33"] body[data-side="visar"] #slide-container .border-b.px-8.py-4 > .flex span[style*="font-size"] { font-size: clamp(1.2rem, min(2.5vw, 3.5vh), 1.75rem) !important; }
  html[data-profil="v33"] body[data-side="visar"] #slide-container .border-b.px-8.py-4 > p { margin-top: 0; }
  /* Tabellane (gloser, grammatikk): radene. */
  html[data-profil="v33"] body[data-side="visar"] #slide-container table :is(th, td).py-4 { padding-block: 0.5rem; }
}
@media (max-width: 640px) {
  html[data-profil="v33"] body[data-side="visar"] #slide-container { padding: 1rem; }
  /* Tabellane ligg i div.bg-stone-800.overflow-hidden: boksen rullar sideveis i staden for å
     avkorte eller bryte midt i ord. Tabellen held display: table. */
  html[data-profil="v33"] body[data-side="visar"] #slide-container .bg-stone-800.overflow-hidden { overflow-x: auto; }
  html[data-profil="v33"] body[data-side="visar"] #slide-container table :is(th, td) { padding: 0.5rem 0.35rem; font-size: 1rem; }
}

/* Tabellane i tilgjengelegheitserklæringa og samsvarssida har tre–fire kolonnar med lang tekst.
   På 320 px blei sida 152 og 466 px for brei (profilen gjer teksten 18 px). Brot midt i ord er
   verre å lese enn rulling, så tabellen ligg i ein boks som rullar sideveis. Tabellen sjølv er
   uendra (display: table, så skjermlesaren held på tabellsemantikken): tilgjengelegheit har ein
   <div data-pt-tabellrull role="region" tabindex="0"> rundt tabellen (berre markup, same tekst),
   samsvar har allereie div.section-inline rundt kvar tabell. All tekst står der og kan nåast;
   ingenting blir skjult eller avkorta. Tastaturfokus får den vanlege profilringen (:focus-visible). */
html[data-profil="v33"] body[data-side="tilgjengelegheit"] [data-pt-tabellrull] { overflow-x: auto; }
@media (max-width: 640px) {
  html[data-profil="v33"] body[data-side="samsvar"] .section-inline { overflow-x: auto; }
}
/* Lastesirkelen i purchase-confirmation.html (border-4 border-green-200 border-t-green-600
   animate-spin): profilen gjer alle border-green-* til --pt-positive, så heile ringen fekk same
   farge og ingenting synte at han går rundt. Lasting er ikkje status (rett/gale), så ringen
   blir nøytral: sporet i kantfargen og toppen i aksentfargen (≥ 3:1 mot sporet i begge
   palettar). Med redusert rørsle står boga stille, men synest framleis. */
html[data-profil="v33"] body .animate-spin:is(.border-t-green-600) { border-color: var(--pt-border); border-top-color: var(--pt-accent); }
/* proveperiode.html har font-family: 'Inter' som inline-stil på <body> (data-side="proveperiode").
   Ein inline-stil slår alle reglar utan !important, så skrifta kan berre bytast slik, og
   regelen står berre på den sida. */
html[data-profil="v33"] body[data-side="proveperiode"] { font-family: var(--pt-font) !important; }

/* ── Fase 7: opprydding (følgjene av 18 px-løftet, så etterslepet frå fase B–6) ── */
/* Botnmenyen (shell.js #main-bottom-nav og Ordtrenaren sin #hub-bottom-nav): etikettane er
   18 px (løftet i 1b). Knappane er w-20 (5rem) med p-2, og «Leksjoner» (83 px) fekk ikkje plass
   i innhaldsboksen på 72 px. Knappane tek breidda etiketten treng, minst 5rem. */
html[data-profil="v33"] body :is(#main-bottom-nav, #hub-bottom-nav) > div > :is(button, a) { width: auto; min-width: 5rem; padding-inline: 0.25rem; }
/* Under 480 px: fire etikettar på til saman om lag 282 px skal stå i 302 px. Rada mistar
   mellomromma (gap-6 = 27 px) og deler breidda ut etter innhaldet, kvar knapp minst 44 px. */
@media (max-width: 479.98px) {
  html[data-profil="v33"] body :is(#main-bottom-nav, #hub-bottom-nav) > div { gap: 0; justify-content: space-around; padding-inline: 0.125rem; }
  html[data-profil="v33"] body :is(#main-bottom-nav, #hub-bottom-nav) > div > :is(button, a) { flex: 1 1 auto; min-width: 44px; padding-inline: 0.125rem; }
}
/* Lenkjene nedst i Profil (Personvern · Bruksvilkår · Brukerstøtte, main-page-views.js) står
   på éi flex-line: på 320 px gjekk «Brukerstøtte» 8 px ut over høgre kant. Rada brytast. */
html[data-profil="v33"] body #tab-profil .flex.justify-center:has(> a[href="/privacy.html"]) { flex-wrap: wrap; row-gap: 0.25rem; }
/* «Hva er nytt?»: versjonslina har font-size 0,875rem inline (service-worker-manager.js);
   !important slår inline-stilen. */
html[data-profil="v33"] body [data-hva-er-nytt] [role="dialog"] > p { font-size: 1rem !important; }
/* Poengtoastane (grammar-points.js): «grammatikkpoeng» var 16 px i <style>-blokka til modulen. */
html[data-profil="v33"] body .gp-toast-inner { font-size: 1rem; }
/* Rotportalen (index.html, eigen <style>): «Åpne →» i korta var 14 px. */
html[data-profil="v33"] body[data-side="portal"] .card .arrow { font-size: 1rem; }
/* Videofasaden i landeskunde (data-video-fasade, innhaldsdataa): «Laster innhold fra YouTube»
   har font-size .875rem inline; !important slår inline-stilen. */
html[data-profil="v33"] body [data-video-fasade] > span[style*="font-size"]:not([aria-hidden="true"]) { font-size: 1rem !important; }
/* Ordtrenar-toppen (tittel, byggmerke og sky-pillen med knappen): med 18 px i pillen gjekk
   knappen 27 px ut over høgre kant på 320 px. Rada brytast, og pillen held seg til høgre. */
html[data-profil="v33"] body header > .px-5.py-3.flex.justify-between:has(#auth-cloud-slot) { flex-wrap: wrap; row-gap: 0.5rem; column-gap: 0.75rem; }
html[data-profil="v33"] body header > .px-5.py-3.flex.justify-between:has(#auth-cloud-slot) > :last-child { margin-left: auto; }
/* bli-med (join-group.html, eigen <style> i px): knappane («Last ned i App Store») var 16 px,
   kodeetiketten og botnteksten 13 px. */
html[data-profil="v33"] body[data-side="bli-med"] :is(.button, .code-label, .footer) { font-size: 1rem; }
/* Dei to store teikna på projektoren (projektor.js): koden (text-8xl, linjehøgd 1) og nedteljinga
   (text-[12rem] leading-none, éitt siffer på 216 px). Linjehøgd 1,5 som all tekst la 54 + 108 px
   til, og nedteljingssifferet hamna under kanten på 1280 × 900. Negativ marg på kvar side tek att
   den ekstra luft (0,25em over og under), så teikna står der dei stod (koden held my-2). */
html[data-profil="v33"] body #konk-projektor [data-testid="kode"] { line-height: 1.5; margin-block: calc(0.5rem - 0.25em); }
html[data-profil="v33"] body #konk-projektor [data-testid="nedteljing"] { line-height: 1.5; margin-block: -0.25em; }

/* Etterslepet frå piloten og fase 2 (P1–P11 i planen for fase 7). */
/* Setningsbygging (drag-drop-sentences.js): eit rett plassert ord får bg-green-100 og
   text-green-800, men .clickable-word-regelen (nøytral brikke) står seinare og tok fargen.
   Utan profilen er orda grøne; teksten «Perfekt!» står framleis under. */
html[data-profil="v33"] body .clickable-word.bg-green-100 { background-color: var(--pt-positive-bg); border-color: var(--pt-positive); color: var(--pt-positive); }
/* Første gale forsøk i lukeøvinga og feilrettinga (gap-text.js, error-correction.js) er
   border-amber-500: eit hint, ikkje eit endeleg gale svar. Profilen gjorde kanten til aksent
   (teal), så han såg ut som eit vanleg felt med ✗. Kanten blir åtvaringsfargen. !important slår
   !important-regelen for .border-amber-500 (spansk/fransk tema i grunnlaget og shell.js). */
html[data-profil="v33"] body :is(.gap-input, .grammar-input).border-amber-500 { border-color: var(--pt-warning-ink) !important; }
/* Smale felt med ✓/✗-ikon: ikonet tek 1,8em til høgre, og i eit w-16-felt stod det att 27 px
   til teksten (44 px utan profilen). Feltet blir breiare med ikonet sin plass (1,8em − 0,5em
   padding) i staden for å krympe teksten. */
html[data-profil="v33"] body :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-green-400, .border-green-500, .border-green-600, .feedback-correct, .border-red-400, .border-red-500, .border-red-600, .feedback-incorrect, .gap-input.border-amber-500, .grammar-input.border-amber-500):is(.w-10) { width: calc(2.5rem + 1.3em); }
html[data-profil="v33"] body :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-green-400, .border-green-500, .border-green-600, .feedback-correct, .border-red-400, .border-red-500, .border-red-600, .feedback-incorrect, .gap-input.border-amber-500, .grammar-input.border-amber-500):is(.w-12) { width: calc(3rem + 1.3em); }
html[data-profil="v33"] body :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-green-400, .border-green-500, .border-green-600, .feedback-correct, .border-red-400, .border-red-500, .border-red-600, .feedback-incorrect, .gap-input.border-amber-500, .grammar-input.border-amber-500):is(.w-14) { width: calc(3.5rem + 1.3em); }
html[data-profil="v33"] body :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-green-400, .border-green-500, .border-green-600, .feedback-correct, .border-red-400, .border-red-500, .border-red-600, .feedback-incorrect, .gap-input.border-amber-500, .grammar-input.border-amber-500):is(.w-16) { width: calc(4rem + 1.3em); }
html[data-profil="v33"] body :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-green-400, .border-green-500, .border-green-600, .feedback-correct, .border-red-400, .border-red-500, .border-red-600, .feedback-incorrect, .gap-input.border-amber-500, .grammar-input.border-amber-500):is(.w-20) { width: calc(5rem + 1.3em); }
html[data-profil="v33"] body :is(input, select, textarea):where(:not(#curriculum-selector)):is(.border-green-400, .border-green-500, .border-green-600, .feedback-correct, .border-red-400, .border-red-500, .border-red-600, .feedback-incorrect, .gap-input.border-amber-500, .grammar-input.border-amber-500):is(.w-24) { width: calc(6rem + 1.3em); }
/* «Fra boka»-blokkene er bygde for ein fast A4-plass og står i appen som dei er
   (book-blocks-render.js lagKort: innhold.innerHTML = bb.html). Produksjonen har sidan 17.10 eigne
   reglar for skjermen (stylesheet.css «"Fra boka" på skjerm», med merkForSkjerm i
   book-blocks-render.js), og dei gjeld òg under profilen:
   - eit felt med svar veks (height: auto), og delane i ei kolonne (flex:N 1 0;min-height:0) får
     innhaldshøgda si. Profilen hadde dei same to rettingane (fase 7 P10, punkt 1–2); dei er tekne
     bort her (oppgåve 8b: geometrien i alle 72 leksjonane er lik med og utan dei);
   - ein inline-storleik blir aldri mindre enn 1rem (18 px under profilen), og felt med px-min-breidd
     krympar til blokka når dei ikkje får plass.
   Det profilen framleis treng, står under: spaltene som brytast i alle breidder (3), golvet på 18 px
   og linjehøgda 1,5 for alle storleikane (4–5), dei lange linene (6a), gåtene som rullar (6b), og
   den smale geometrien til og med 640 px (6). Der ein produksjonsregel og ein profilregel møtest,
   seier kommentaren kva som slår kva.
   3. To spalter (flex:1 1 0; min-width:0) med skrivefelt på min-width:190px: på 320 px er
      spalta om lag 100 px, og felta går inn i nabospalta. Spaltene brytast under kvarandre når
      innhaldet ikkje får plass. !important slår inline-min-width:0. */
html[data-profil="v33"] body [data-book-block-id] div:has(> [style*="flex:1 1 0;min-width:0" i]) { flex-wrap: wrap; }
html[data-profil="v33"] body [data-book-block-id] [style*="flex:1 1 0;min-width:0" i] { min-width: min-content !important; }
/* 4. Teksten i blokkene har eigne inline-storleikar frå A4-sida: 15px, 14px og .78em–.95em
      (8–15 px), òg i font-kortforma (font:600 15px/1 i ordleterutenettet). Brødtekst er minst
      18 px (fase 7, P10b): kvar inline-storleik under 18 px eller under 1em/1rem blir 1rem.
      Storleikar på 1rem og meir (overskrifta 1.02rem, 2em) står. !important slår inline-storleiken.
      Ingenting blir gøymt eller flytta. */
html[data-profil="v33"] body [data-book-block-id] :is([style*="font-size:8px" i], [style*="font-size: 8px" i], [style*="font-size:9px" i], [style*="font-size: 9px" i], [style*="font-size:10px" i], [style*="font-size: 10px" i], [style*="font-size:11px" i], [style*="font-size: 11px" i], [style*="font-size:12px" i], [style*="font-size: 12px" i], [style*="font-size:13px" i], [style*="font-size: 13px" i], [style*="font-size:14px" i], [style*="font-size: 14px" i], [style*="font-size:15px" i], [style*="font-size: 15px" i], [style*="font-size:16px" i], [style*="font-size: 16px" i], [style*="font-size:17px" i], [style*="font-size: 17px" i], [style*="font-size:." i], [style*="font-size: ." i], [style*="font-size:0." i], [style*="font-size: 0." i], [style*="font:8px" i], [style*="font: 8px" i], [style*="font:600 8px" i], [style*="font:700 8px" i], [style*="font:9px" i], [style*="font: 9px" i], [style*="font:600 9px" i], [style*="font:700 9px" i], [style*="font:10px" i], [style*="font: 10px" i], [style*="font:600 10px" i], [style*="font:700 10px" i], [style*="font:11px" i], [style*="font: 11px" i], [style*="font:600 11px" i], [style*="font:700 11px" i], [style*="font:12px" i], [style*="font: 12px" i], [style*="font:600 12px" i], [style*="font:700 12px" i], [style*="font:13px" i], [style*="font: 13px" i], [style*="font:600 13px" i], [style*="font:700 13px" i], [style*="font:14px" i], [style*="font: 14px" i], [style*="font:600 14px" i], [style*="font:700 14px" i], [style*="font:15px" i], [style*="font: 15px" i], [style*="font:600 15px" i], [style*="font:700 15px" i], [style*="font:16px" i], [style*="font: 16px" i], [style*="font:600 16px" i], [style*="font:700 16px" i], [style*="font:17px" i], [style*="font: 17px" i], [style*="font:600 17px" i], [style*="font:700 17px" i]) { font-size: 1rem !important; }
/* 5. Linjehøgd minst 1,5: inline 1.35–1.45, /1 i font-kortforma, og svarfelta der renderaren set
      «line-height: 1.15em» eller «1.35em» (lik felthøgda) når fasiten er vist — same mønster.
      !important slår inline-stilen. */
html[data-profil="v33"] body [data-book-block-id] :is([style*="line-height:1.0" i], [style*="line-height: 1.0" i], [style*="line-height:1.1" i], [style*="line-height: 1.1" i], [style*="line-height:1.2" i], [style*="line-height: 1.2" i], [style*="line-height:1.3" i], [style*="line-height: 1.3" i], [style*="line-height:1.4" i], [style*="line-height: 1.4" i], [style*="line-height:1;" i], [style*="line-height: 1;" i], [style*="px/1 " i], [style*="px/1.0" i], [style*="px/1.1" i], [style*="px/1.2" i], [style*="px/1.3" i], [style*="px/1.4" i]) { line-height: 1.5 !important; }
/* 6a. Dei lange skrivelinene (min-width:640px, ei heil A4-tekstbreidd) er breiare enn kortet òg
      mellom 641 og om lag 900 px vindaugsbreidd (747 px mot 705 på 768), og .bokseksjon klipte dei.
      Ruling (fase 7, P10b): dei fyller kortet, men aldri meir enn 640 px. Der kortet er breiare
      enn 640 px (1280), er lina 640 px som før. Med fasiten vist har renderaren skrive stilen om
      («min-width: 640px» med mellomrom), så begge formene står. !important slår inline-min-width. */
html[data-profil="v33"] body [data-book-block-id] :is([style*="min-width:640px" i], [style*="min-width: 640px" i]) { min-width: 0 !important; width: 100%; max-width: 640px; box-sizing: border-box; }
/* 6b. Ved alle breidder, utan endring der innhaldet får plass: eit svar kan brytast inne i eit ord
      når ordet er breiare enn plassen (månadskorta i 8.1 på 768 px), og bokstavgåtene
      (ordleterutenettet, kryssordet med Lösungswort, ordslangen med månadene) kan ikkje brytast
      utan å miste meininga (WCAG 1.4.10, som Jeopardy og bingo): er dei breiare enn kortet, rullar
      dei sideveis i sin eigen boks i staden for å bli klipte. Rutene held storleiken sin. Begge er
      flex-element, så min-width: 0 held boksen innanfor rada. */
html[data-profil="v33"] body [data-book-block-id] [data-blank] { overflow-wrap: anywhere; }
html[data-profil="v33"] body [data-book-block-id] :is(div[style*="display:inline-block" i]:has(> div > [style*="width:27px" i]), div:has(> div[style*="white-space:nowrap" i] + div[style*="white-space:nowrap" i]), div[style*="white-space:nowrap" i]:has(> div)) { min-width: 0; overflow-x: auto; }
html[data-profil="v33"] body [data-book-block-id] div[style*="display:inline-block" i] > div > [style*="width:27px" i] { flex: none; }
/* Ein gåte som rullar, får tabindex="0", role="region" og eit namn frå book-blocks-render.js
   (merkRullandeGater). Fokusringen står INNANFOR boksen: utanfor ville kortet eller seksjonen
   kunne klippe han. Same doble ring (mørk og lime) som elles. !important slår !important-regelen
   for :focus-visible i grunnlaget. */
html[data-profil="v33"] body [data-book-block-id] [role="region"][tabindex="0"]:focus-visible { outline-offset: -6px !important; box-shadow: inset 0 0 0 3px var(--pt-focus-outer) !important; }
/* 6. Til og med 640 px vindaugsbreidd er blokka smalare enn A4-sida ho er laga for. På 320 px stod
      det 84 px att til innhaldet (fire lag med 27/16 px luft), og tabellar, spalter, rutenett og
      skrivelinene på 55–640 px gjekk ut over kortet, der .bokseksjon (overflow: hidden) klipte dei.
      Over 640 px er geometrien uendra. Ingenting blir klipt:
      - mindre luft i kortet og blokka (!important slår blokka sin inline-padding), og seksjonen
        klipper ikkje. Lufta i seksjonskroppen (0,5rem) og i tabellcellene (0,25rem, med brot inne
        i ord) kjem frå stylesheet.css («Fra boka» på skjerm, 5 og 8) og er ikkje gjenteken her;
      - skrivelinene (inline px-min-width) krympar til blokka og fyller breidda ho har
        (!important slår inline-min-width);
      - spaltene står under kvarandre (flex:1 1 0;min-width:0 i vg1-tysk1, flex:1;flex:1 1 auto i
        us-utgåvene; !important slår inline-flex og min-width:0);
      - rutenetta (kort for dagar, klede, månader, teikneserie) får så mange kolonnar det er plass
        til, i same rekkjefølgje (!important slår inline-grid-template-columns);
      - svar, overskrifta i blokka og tekstkolonna ved sida av eit bilete/ein sirkel
        (flex:1;line-height) kan brytast inne i eit ord når ordet er breiare enn plassen
        («Geburtstagskalender», «Hausaufgaben.»);
      - kryssordet får heile breidda, med stikkorda under seg (rullinga i gåtene: 6b). */
@media (max-width: 640px) {
  html[data-profil="v33"] body .bokseksjon { overflow: visible; }
  html[data-profil="v33"] body [data-book-block-id] { padding-inline: 0.5rem; }
  html[data-profil="v33"] body [data-book-block-id] > div > div { padding-inline: 0.5rem !important; }
  html[data-profil="v33"] body [data-book-block-id] :is([data-blank], span)[style*="min-width:" i]:not([style*="min-width:0" i]) { min-width: 0 !important; width: 100%; box-sizing: border-box; }
  html[data-profil="v33"] body [data-book-block-id] div:has(> [style*="flex:1;flex:1 1 auto" i]) { flex-wrap: wrap; }
  /* Spaltene: stylesheet.css («Fra boka» på skjerm, 6) gjev alle borna i ei rad med berre flex:1-
     spalter flex-basis: 12rem !important (0,5,1), så på om lag 500–640 px stod to spalter side om
     side. Under profilen står dei under kvarandre: seksjonskroppen og rada i veljaren gjev 0,5,2,
     som slår 0,5,1 (begge !important; !important slår òg inline-flex og min-width:0). */
  html[data-profil="v33"] body .bokseksjon-body [data-book-block-id] :has(> :is([style*="flex:1 1 0;min-width:0" i], [style*="flex:1;flex:1 1 auto" i])) > :is([style*="flex:1 1 0;min-width:0" i], [style*="flex:1;flex:1 1 auto" i]) { flex-basis: 100% !important; min-width: 0 !important; }
  html[data-profil="v33"] body [data-book-block-id] [style*="grid-template-columns" i] { grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr)) !important; }
  html[data-profil="v33"] body [data-book-block-id] :is([data-blank], h2, [style*="flex:1;line-height" i]) { overflow-wrap: anywhere; min-width: 0; }
  html[data-profil="v33"] body [data-book-block-id] div:has(> div > div[style*="white-space:nowrap" i] + div[style*="white-space:nowrap" i]) { flex-wrap: wrap; }
  html[data-profil="v33"] body [data-book-block-id] div:has(> div[style*="white-space:nowrap" i] + div[style*="white-space:nowrap" i]) { flex: 1 1 100%; }
  /* Ordleteruta: stylesheet.css («Fra boka» på skjerm, 9) lèt rutene dele breidda (display:block
     på rutenettet, width:auto og height:1.5rem !important på rutene): ruta vart 13 px brei (målt
     på 320 og 640 px) rundt ein bokstav på 18 px. Under profilen held ruta 27 px, og
     rutenettet rullar i sin eigen boks (6b), som book-blocks-render.js gjer fokuserbar.
     !important slår !important-reglane i stylesheet.css (0,3,1 og 0,2,0); 27px er same verdi som
     inline-stilen veljaren les. */
  html[data-profil="v33"] body [data-book-block-id] div[style*="display:inline-block" i]:has(> div > [style*="width:27px" i]) { display: inline-block !important; }
  html[data-profil="v33"] body [data-book-block-id] div[style*="display:inline-block" i] > div > [style*="width:27px;height:27px" i] { width: 27px !important; height: 27px !important; }
  /* Seksjonen klipper ikkje lenger, så hjørna til overskriftsflata (peikar over) blir runda her:
     12 px som seksjonen, 2 px mindre innanfor ramma til ei innfelt seksjon; open: berre øvst. */
  html[data-profil="v33"] body .bokseksjon-summary { border-radius: 0.75rem; }
  html[data-profil="v33"] body .bokseksjon--innfelt > .bokseksjon-summary { border-radius: calc(0.75rem - 2px); }
  html[data-profil="v33"] body .bokseksjon[open] > .bokseksjon-summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
}
/* Spela i Dialog-fana og minnekorta i grammatikken (fase 7, oppgåve 11b: dei siste funna i
   `--alle`, alle til stades før fase 7).
   Jeopardy (dialog/jeopardy.js): brettet er repeat(N, 1fr) inline, med alle kategorinamna først
   og så rad for rad (100 i kvar kategori, så 200 …). Regelen som gjev «.tab-content
   .grid > *» min-width: 0 (over) lèt kolonnane krympe under innhaldet, så rullinga i .bg-blue-900 slo
   aldri inn: på 320 px vart kolonnane 46 px, namna og tala (45 px) flaut inn i nabokolonna og
   2–16 px ut over venstre kant. Namna gjekk òg ut av kolonna på 640–1024 px (målt;
   «Vakansjevokabular» er om lag 200 px i 22,5 px).
   Under 640 px står brettet i kolonnar på minst 11rem og rullar sideveis i sin eigen boks
   (.bg-blue-900 har overflow-x: auto lenger oppe), same tal kategoriar eller ikkje. Synleg
   rekkjefølgje er då DOM-rekkjefølgja, så Tab og skjermlesar følgjer det eleven ser; rutene er
   knappar, så Tab når dei og rullar dei fram (Geir 22.10: rulle, ikkje stable; WCAG 2.4.3).
   Rutene heiter berre poengtalet (jeopardy.js); eit namn som «Reisevokabular 100» krev ei
   endring i jeopardy.js. */
@media (max-width: 639.98px) {
  html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 > .grid > * { min-width: 11rem; }
}
/* Frå 640 px står brettet i kolonnar, så synleg rekkjefølgje og Tab-rekkjefølgje er den same.
   Namna står i 1rem med mindre luft på sidene (p-5 = 22,5 px; på 1280 px låg «Vakansjevokabular»
   ut i lufta), og på 640–1023 px blir dei orddelte med bindestrek (hyphens: auto etter lang="no"
   på sida; kolonnane er om lag 103–127 px). Tala står der i 2rem (2,5rem gjekk ut av ruta). Eit
   namn som framleis er breiare enn plassen, blir brote inne i ordet i staden for å gå inn i
   nabokolonna eller ut over kanten; den regelen kjem etter overflow-wrap: normal over (same
   spesifisitet). Frå 1280 px står namna i text-xl som før. */
html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 > .grid > div { overflow-wrap: anywhere; }
@media (min-width: 640px) {
  html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 > .grid > div { padding-inline: 0.25rem; }
}
@media (min-width: 640px) and (max-width: 1279.98px) {
  html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 > .grid > div { font-size: 1rem; }
}
@media (min-width: 640px) and (max-width: 1023.98px) {
  html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 > .grid > div { hyphens: auto; }
  html[data-profil="v33"] body .jeopardy-game > .bg-blue-900 > .grid > .jeopardy-tile .points { font-size: 2rem; }
}
/* Minnekorta for preposisjonane (grammar-modules/prepositions/: «aus bei mit nach seit von zu» i
   grid-cols-7, «durch für gegen ohne um» med tyding i grid-cols-5): innanfor tre lag med luft
   var rutenettet 140 px på 320 px, og kvar rute 18–21 px, så orda vart delte bokstav for bokstav
   og «mit» låg over naboen. Korta brytast i rader i same rekkjefølgje og fyller rada (på breie
   skjermar står dei i éi rad som før), og orda står heile. */
html[data-profil="v33"] body .prepositions-tool .grid:is(.grid-cols-5, .grid-cols-7):has(> .p-2.rounded-lg) { display: flex; flex-wrap: wrap; justify-content: center; }
html[data-profil="v33"] body .prepositions-tool .grid:is(.grid-cols-5, .grid-cols-7) > .p-2.rounded-lg { flex: 1 1 auto; }
/* Bingo (dialog/bingo.js): uttrykka står i text-2xl (27 px) i ruter på om lag 182 px (1280),
   og eit langt ord («Einkaufszentrum», «Haupteingang»; «Schokoladenkuchen» finst òg i vg2-dataa)
   gjekk ut over ruta, på 1280 px og ned til 640 px (målt). Uttrykket står i 1rem (under 640 px:
   regelen over) og 1,125rem (20,25 px) frå 1024 px, og ruta har inga luft på sidene (teksten står
   midt i ruta, innanfor ramma). Under 768 px er brettet minst 35rem (34rem over, under 640 px)
   og rullar i kortet sitt der det er breiare, så «Einkaufszentrum» (om lag 144 px i 18 px) står
   heilt i ruta (på 640–767 px var rutene elles om lag 126 px). Er eit ord framleis breiare enn
   ruta, blir det brote inne i ordet i staden for å gå ut over kanten. */
html[data-profil="v33"] body .tab-content .bingo-cell { padding-inline: 0; }
html[data-profil="v33"] body .tab-content .bingo-cell > span { overflow-wrap: anywhere; }
html[data-profil="v33"] body .tab-content .bingo-cell > span:first-child { font-size: 1rem; }
@media (max-width: 767.98px) {
  html[data-profil="v33"] body .tab-content .bingo-board { min-width: 35rem; }
}
@media (min-width: 1024px) {
  html[data-profil="v33"] body .tab-content .bingo-cell > span:first-child { font-size: 1.125rem; }
}
/* ── Fase 7: skalet, knutepunkta og modalane (S1–S12, etterslepet frå fase 3) ── */
/* S1. Poengtoasten (progress/grammar-points.js, <style> i modulen).
   a) Han stod på left: 50 % med translateX(-50 %), men nøkkelbileta (gp-slide-in) set transform
      utan translateX: medan han glei inn, stod venstrekanten midt i vindauget, og på 320 px gjekk
      han 100 px ut over høgre kant. Produksjonen midtstiller han no sjølv utan transform (left og
      right 0, margin-inline: auto, width: max-content; fix/poengtoast-kant). Profilen gjev han
      berre meir luft til kantane (1rem kvar side mot 8 px).
   b) Med «redusert rørsle» tok profilen animasjonen bort (animation: none nedst i fila), så
      animationend kom aldri: toasten vart ståande, og kvar ny la seg oppå den førre. No køyrer
      nøkkelbileta med steps(1, jump-start): kvart steg hoppar rett til sluttverdien, så toasten
      står fullt synleg på staden i 2 s og er borte frå 2 s (animationend ved 2,5 s), utan rørsle
      og utan ei toning der teksten ei stund har for svak kontrast.
   c) Fleire toastar på ein gong: berre den nyaste blir vist. Dei eldre er usynlege til
      animasjonen deira er ferdig (visibility, ikkje display, så animationend framleis kjem).
   d) Under 768 px med botnmeny dekte toasten sky-pillen og sidetittelen («Min Profil» på
      knutepunkta, «Lagres lokalt» i toppfeltet til Ordtrenaren, som ikkje rullar). Han står over
      botnmenyen i staden, i eit felt innhaldet held fritt (S1e). */
html[data-profil="v33"] body .gp-toast { max-width: calc(100% - 2rem); }
html[data-profil="v33"] body .gp-toast:has(~ .gp-toast) { visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
  /* !important slår animation: none !important nedst i fila og transform frå nøkkelbileta */
  html[data-profil="v33"] body .gp-toast { animation: gp-slide-in 2.5s steps(1, jump-start) forwards !important; transform: none !important; }
}
@media (max-width: 767.98px) {
  html[data-profil="v33"] body:has(> :is(#main-bottom-nav, #hub-bottom-nav)) > .gp-toast { top: auto; bottom: calc(6rem + var(--pt-plass-varsel, 0px) + var(--pt-plass-synk, 0px) + env(safe-area-inset-bottom)); }
  /* Ein treningsmodus i Ordtrenaren (#exercise-container, absolute inset-0) ligg over
     botnmenyen: der står toasten nedst, i feltet treningsvisinga held fritt (under). */
  html[data-profil="v33"] body:has(> #hub-bottom-nav):has(#exercise-container:not(.hidden)) > .gp-toast { bottom: calc(1rem + env(safe-area-inset-bottom)); }
}
/* e) Feltet over botnmenyen (toasten og synkmeldinga, S12): innhaldet sluttar over det, så det
   som står nedst, kan rullast fram. 5rem (inline frå shell.js, pb-20 i Ordtrenaren) gav berre
   plass til menyen (95 px på 320 px). Feltet er fast, ikkje berre medan ei melding står der:
   elles hoppar sida når meldinga går bort og eleven står nedst. Varselet og synkmeldinga legg
   radene sine til (S13). !important slår inline-stilen. */
html[data-profil="v33"] body:has(> #main-bottom-nav) > .container { padding-bottom: calc(10rem + var(--pt-plass-varsel, 0px) + var(--pt-plass-synk, 0px) + env(safe-area-inset-bottom)) !important; }
html[data-profil="v33"] body:has(> #hub-bottom-nav) #app-container { padding-bottom: calc(10rem + var(--pt-plass-varsel, 0px) + var(--pt-plass-synk, 0px) + env(safe-area-inset-bottom)); }
html[data-profil="v33"] body:has(> #hub-bottom-nav) #exercise-container { padding-bottom: calc(5rem + env(safe-area-inset-bottom)); }
/* S3 (kanten på «Læringspoeng i dag») står i regelen for sporet under knutepunkta (fase 3). */
/* S8. Vekekalenderen (main-page-views.js): passerte og framtidige dagar var like (bg-stone-100
   med text-stone-400 og text-stone-300, som profilen gjev same farge). Ein framtidig dag har
   inga flate, berre ein stipla ring: skilnaden ligg i forma, ikkje berre i fargen. Ringen er ein
   outline utanfor sirkelen: på 320 px er sirkelen 22 px og «18» 20 px, ein kant inni ville
   skore i sifra. */
html[data-profil="v33"] body #week-calendar-grid .bg-stone-100.text-stone-300 { background-color: transparent; outline: 2px dashed var(--pt-field-border); outline-offset: 0; color: var(--pt-ink-secondary); }
/* S9. Utmerkingsmodalen i lys modus: lime-stripa hadde 1,14:1 mot tinten og OK-knappen
   1,26:1 mot kvitt, utan synleg kant. I lys modus står stripa og knappekanten i
   overskriftsfargen (knappen er framleis lime); i mørk modus er lime alt tydeleg (7:1). */
html[data-profil="v33"] body #achievement-modal-backdrop :is(.border-l-4, .achievement-modal-ok) { border-color: var(--pt-heading); }
@media (prefers-color-scheme: dark) {
  html[data-profil="v33"]:where(:not([data-tema="lys"])) body #achievement-modal-backdrop :is(.border-l-4, .achievement-modal-ok) { border-color: var(--pt-lime); }
}
html[data-profil="v33"]:where([data-tema="mork"]) body #achievement-modal-backdrop :is(.border-l-4, .achievement-modal-ok) { border-color: var(--pt-lime); }
/* S11. Oppdateringsvarselet (utils/sw-oppdatering.js, fixed bottom-20) dekte lenkjene nedst i
   Profil og stod 5 px inn i botnmenyen. Med botnmeny står det over menyen, og medan det står
   der, held innhaldet plass til det òg (raden hans i S13, lagd til feltet i S1e). Det står til
   eleven vel, så sida hoppar berre etter eit trykk. */
html[data-profil="v33"] body:has(> :is(#main-bottom-nav, #hub-bottom-nav)) > [data-sw-varsel] { bottom: calc(6rem + env(safe-area-inset-bottom)); }
/* S12. Synkmeldinga (#sync-status, cloud-sync.js: fixed bottom-4 right-4) låg under
   botnmenyen («Ingen ny data» var ikkje å sjå). Ho står over menyen, i feltet frå S1e, og over
   varselet når det står der (S13). På 320 px gjekk ei lang melding heilt ut til venstre kant. */
html[data-profil="v33"] body:has(> :is(#main-bottom-nav, #hub-bottom-nav)) #sync-status { bottom: calc(6rem + var(--pt-plass-varsel, 0px) + env(safe-area-inset-bottom)); max-width: calc(100% - 2rem); }
/* S13. Varselet, synkmeldinga og toasten på ein gong: S1, S11 og S12 sette alle tre i same felt
   over botnmenyen, så dei dekte kvarandre (toasten over varselet, toasten over synkmeldinga etter
   ein verbtest i Ordtrenaren, synkmeldinga over varselet på 320 px). Kvar får si eiga rad,
   nedanfrå: varselet (står til eleven vel), synkmeldinga, toasten (2,5 s). Står varselet der,
   flyttar synkmeldinga og toasten seg opp med raden hans; står synkmeldinga der, toasten med
   hennar, og innhaldsfeltet (S1e) veks like mykje.
   CSS kan ikkje måle ei høgd: raden er den største høgda målt med dei lengste tekstane appen har,
   i rem (han følgjer tekststorleiken), med 0,5rem luft.
   - Varselet: 130 px på 320–480 px («A new version of the Word Trainer is ready.», tre liner),
     71 px frå 600 px. Rad: 8rem (144 px) under 768 px, 4,5rem (81 px) frå 768 px.
   - Synkmeldinga: 104 px på 320 px («Synkronisert 24 leksjoner og 3 rapporter,
     2 tilbakemeldinger», cloud-sync.js, tre liner), 76 px på 375–414 px, 47 px frå 768 px.
     Rad: 6,5rem (117 px) under 768 px og 3,5rem (63 px) frå 768 px.
   Synkmeldinga står berre nokre sekund; feltet hennar følgjer henne (ruling, fase 7 oppgåve 5).
   Utan :has() fell reglane bort, og alt står der det stod før fase 7. */
html[data-profil="v33"] body:has(> [data-sw-varsel]) { --pt-plass-varsel: 4.5rem; }
html[data-profil="v33"] body:has(#sync-status:not(.hidden)) { --pt-plass-synk: 3.5rem; }
@media (max-width: 767.98px) {
  html[data-profil="v33"] body:has(> [data-sw-varsel]) { --pt-plass-varsel: 8rem; }
  html[data-profil="v33"] body:has(#sync-status:not(.hidden)) { --pt-plass-synk: 6.5rem; }
}
/* S13b. Same to meldingane på ei side utan botnmeny (leksjonane): varselet står på bottom-20 og
   synkmeldinga på bottom-4 (inline-klassane i modulane), og med teksten på 18 px er synkmeldinga
   104 px høg på 320 px, høgare enn dei 72 px mellom dei: ho låg 32 px inn i varselet (målt i
   vg1-1-2, oppgåve 8b). Same rekkjefølgje som S13: varselet står (til eleven vel), og
   synkmeldinga, som berre står nokre sekund, flyttar seg opp over raden hans (8rem / 4,5rem, S13).
   Poengtoasten står øvst på desse sidene og er ikkje med i feltet. */
html[data-profil="v33"] body:not(:has(> :is(#main-bottom-nav, #hub-bottom-nav))):has(> [data-sw-varsel]) #sync-status { bottom: calc(5rem + var(--pt-plass-varsel, 0px)); }

/* ── Fase 7: Ordtrenaren, trenarane, gloseprøva og bli-med (T1–T10, etterslepet frå fase 4) ── */
/* T3. bli-med (join-group.html) på 320 px: body (24 px), kortet (28 px) og .empty (24 px) åt 152 px
   av breidda, så overskrifta hadde 166 px og «Vennegrupper» braut inne i ordet («Vennegrupp / er»).
   Under 480 px er luft rundt og i kortet mindre: innhaldet får 248 px (knappane er min-width 240). */
@media (max-width: 479.98px) {
  html[data-profil="v33"] body[data-side="bli-med"] { padding: 1rem; }
  html[data-profil="v33"] body[data-side="bli-med"] .card { padding: 1.5rem 1rem; }
  html[data-profil="v33"] body[data-side="bli-med"] .empty { padding: 0; }
}
/* T10. Kodeetiketten står som «KODE» i sida (berre store bokstavar). Ho blir «Kode»: små bokstavar
   og stor forbokstav. Storleiken (18 px) kjem frå regelen i «Fase 7: opprydding». !important slår
   text-transform: none !important (body * i grunnlaget); ::first-letter er ikkje med i den. */
html[data-profil="v33"] body[data-side="bli-med"] .code-label { text-transform: lowercase !important; }
html[data-profil="v33"] body[data-side="bli-med"] .code-label::first-letter { text-transform: uppercase; }
/* T4. Verbtrenaren: nivåvalet (verb-test.js, fire flex-1-knappar i ei rad) gav kvar knapp 51 px på
   320 px, og «Kapitlene» (92 px i 18 px) gjekk inn under «Basis» (òg «Utvidet» under «Alle»).
   Knappane er så breie som teksten og deler resten; får dei ikkje plass, brytast rada (2 + 2). */
html[data-profil="v33"] body :has(> .nivaa-knapp) { flex-wrap: wrap; }
html[data-profil="v33"] body .nivaa-knapp { flex: 1 1 auto; }
/* T5. Lukkeknappen i trenarane (exit-skriv-btn, exit-verb-test-btn, exit-vocab-test-btn: absolute
   top-4 right-4, 54 px høg) i fullskjermflata (#vocab-exercise-area, flex items-center): på
   320 × 568 starta kortet 1 px under toppen av flata, og X-en låg over retningsknappen og
   «Spørsmål 1 / 20» (på 375 × 667 over hjørnet av retningsknappen). Flata held toppen fri for
   X-en (18 + 54 + 9 px), og kortet står midt i resten med auto-marg (som modalane): eit høgt kort
   byrjar under X-en og rullar, i staden for at sentreringa klipper toppen. */
html[data-profil="v33"] body #vocab-exercise-area:has(> button.absolute[id^="exit-"]) { align-items: flex-start; padding-top: 4.5rem; }
html[data-profil="v33"] body #vocab-exercise-area:has(> button.absolute[id^="exit-"]) > :not(button) { margin-block: auto; }
/* Skriv-toppen (write.js): «Skriv» og «Spørsmål 1 / 20» stod kant i kant på 320 px. */
html[data-profil="v33"] body #vocab-exercise-area .flex.justify-between.items-center:has(> p > #skriv-progress) { column-gap: 0.75rem; }
/* T6. «Blitz-modus» (verb-test.js) har ein mørk gradient og fekk spelhovudflata (--pt-panel), som i
   mørk modus er same farge som kortet: knappen var berre tekst utan flate. Han er ei startknapp
   som «Start Test» og får same fylte flate (lime i mørk, petrol i lys). */
html[data-profil="v33"] body #start-verb-blitz-btn { background-color: var(--pt-primary); color: var(--pt-on-primary); }
/* T7. Gloseprøve-modalen (glossary-test-student-ui.js, flex items-center utan rulling): på
   320 × 360 med feilmeldinga stod toppen av kortet 35 px over skjermkanten (tittel og lukkeknapp),
   og ingenting rulla dit. Same mønster som dei andre dialogane: overlegget byrjar øvst og rullar,
   auto-marga sentrerer kortet når det er plass. */
html[data-profil="v33"] body #glossary-test-modal { align-items: flex-start; overflow-y: auto; }
html[data-profil="v33"] body #glossary-test-modal > div { margin-block: auto; }
/* T9. Tidtakaren i ordkortknappane (flashcards.js, #timer-action/#timer-next) var ei flate med 30 %
   av knappefargen over knappen: i praksis usynleg. Ho blir ei line nedst i knappen i tekstfargen
   (currentColor held 4,5:1 mot knappen), og veks i breidd som før (inline width frå skriptet).
   Lina ligg i botnpaddingen, ikkje under teksten. */
html[data-profil="v33"] body :is(#btn-action, #btn-next) > span[id^="timer-"] { top: auto; height: 0.375rem; background-color: currentColor; }

/* ── Fase 7: Konkurranse (K1–K8, etterslepet frå fase 5) ── */
/* K2 og K3. Projektorflata (projektor.js): ordregnet (absolutt, inset 0) låg over heile visinga og
   gjekk over koden, QR-koden og musikklina; og på 1280 px stod alt i éi kolonne under kvarandre
   (kode, QR, musikk, så lobbyen), så lobbylista og Start hamna under kanten. Flata blir eit
   rutenett: innhaldsboksen (data-pt-projektorinnhald) blir «display: contents», så borna hans
   og regnet er rutene. Regnet får berre spelruta (melding, kropp og knappar), aldri koden eller
   QR-en; borna er relative, så dei blir teikna over regnet (som innhaldsboksen var før). */
html[data-profil="v33"] body #konk-projektor [data-pt-projektorflate] {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "hode" "qr" "lyd" "melding" "kropp" "knappar";
}
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] { display: contents; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > * { position: relative; min-width: 0; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > header { grid-area: hode; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > [data-pt-qr] { grid-area: qr; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > [data-pt-lydrad] { grid-area: lyd; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > p[role="alert"] { grid-area: melding; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > section { grid-area: kropp; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > [data-pt-knapperad] { grid-area: knappar; }
html[data-profil="v33"] body #konk-projektor [data-pt-projektorflate] > [data-testid="ordregn"] { grid-row: melding-start / knappar-end; grid-column: 1 / -1; }
/* K3. Frå 1024 px: breiare flate (80rem i staden for max-w-5xl) og to kolonner øvst, kode og musikk
   til venstre og QR-koden til høgre; lobbyen, spelet og pallen får heile breidda under. Utan QR
   (stengd) står alt i éi kolonne som før. Projektoren blir lågare, ikkje høgare. */
@media (min-width: 1024px) {
  html[data-profil="v33"] body #konk-projektor { max-width: 80rem; }
  html[data-profil="v33"] body #konk-projektor [data-pt-projektorflate]:has(> [data-pt-projektorinnhald] > [data-pt-qr]:not(.hidden)) {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "hode qr" "lyd qr" "melding melding" "kropp kropp" "knappar knappar";
    column-gap: 3rem;
  }
  html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > header { align-self: end; }
  html[data-profil="v33"] body #konk-projektor [data-pt-projektorinnhald] > [data-pt-lydrad] { align-self: start; }
}
/* K1. Adressa («Bli med på ordtrener.no/K7M2QX», text-3xl) braut inne i koden på 320 px: adressa
   alene er breiare enn skjermen. Storleiken følgjer breidda (aldri under 18 px) til ho er
   1,875rem att frå om lag 480 px. */
html[data-profil="v33"] body #konk-projektor [data-testid="adresse"] { font-size: clamp(1rem, 7vw, 1.875rem); }
/* K1. Under 640 px: mindre sideluft på projektoren, podiet blir ei liste (1, 2, 3) med plass-
   blokka til venstre for namn og poeng (kolonnene på 80 px braut namna bokstav for bokstav), og
   ei rad i topplista lèt namnet gå på eiga line når det ikkje får plass ved plass og flagg
   («kallenamn» gjekk ut over lime-raden). */
@media (max-width: 639.98px) {
  html[data-profil="v33"] body #konk-projektor { padding-inline: 1rem; }
  html[data-profil="v33"] body #konk-projektor [data-testid="pall"] { flex-direction: column; align-items: stretch; gap: 0.75rem; }
  html[data-profil="v33"] body #konk-projektor [data-testid^="pall-"] { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr); column-gap: 0.75rem; align-items: center; width: auto; }
  html[data-profil="v33"] body #konk-projektor [data-testid="pall-1"] { order: -1; }
  html[data-profil="v33"] body #konk-projektor [data-testid^="pall-"] > span { grid-column: 2; justify-self: start; text-align: start; }
  html[data-profil="v33"] body #konk-projektor [data-testid^="pall-"] > div { grid-column: 1; grid-row: 1 / span 2; align-self: stretch; height: auto; margin-top: 0; padding-block: 0.5rem; border-radius: 1rem; align-items: center; }
  html[data-profil="v33"] body #konk-projektor [data-testid="toppliste"] > li { flex-wrap: wrap; column-gap: 0.75rem; }
  html[data-profil="v33"] body #konk-projektor [data-testid="toppliste"] > li > span:first-child { width: auto; }
  html[data-profil="v33"] body #konk-projektor [data-testid="toppliste"] > li > span:last-child { flex: 1 1 auto; min-width: 0; }
  /* «1:00 igjen» og «12 spillere» over topplista braut kvar for seg; rada brytast i staden. */
  html[data-profil="v33"] body #konk-projektor section > div:has(> [data-testid="framdrift"]) { flex-wrap: wrap; column-gap: 1rem; }
}
/* K6. Elevsida, resultatet: «2. plass av 14» (text-4xl) braut som «2. plass av / 14» på 320 px.
   Balansert bryting gjev «2. plass / av 14»; nettlesarar utan text-wrap bryt som før. */
html[data-profil="v33"] body [data-testid="plass"] { text-wrap: balance; }

/* ── Fase 7: lærarvisingane og infosidene (L1–L12, etterslepet frå fase 6) ── */
/* L10 og L4. Radene i prøveresultatet bryt på 320 px (fase 6): namnet får éi line, og resten
   (forsøk, poeng, bonusknappen) går på line to. Den lina byrja under rangcella, ikkje under
   namnet. No står rangcella i venstre luft på rada (negativ marg like stor som cella og
   mellomrommet), så line to byrjar der namnet byrjar. På éi line står alt som før.
   Rangcella var 2rem: «#100» (43 px i 18 px) gjekk ut over henne. Ho er no minst 2,5rem (plass
   til «#999») og veks med teksten i staden for å spøle over; då flyttar berre namnet i den rada
   seg. Til og med 640 px er mellomromma 0,5rem, så line to (forsøk, «96% ✓», «+1 ✓») held seg på
   éi line på 320 px trass innrykket; ei rad med brotmerke («⚠ 2») får ei tredje line der.
   Klassedetaljen (#tcd-content) står som før: der er line to breiare (rekkje, poeng og
   Fjern-knappen), og med innrykk gjekk Fjern-knappen ned på ei tredje line på 320 px. Rangcella
   der er 2,5rem (w-10) og rommar «#100». */
html[data-profil="v33"] body #tr-content > .flex.items-center.border-b { padding-left: 4.25rem; }
html[data-profil="v33"] body #tr-content > .flex.items-center.border-b > .w-8:first-child { width: auto; min-width: 2.5rem; margin-left: -3.25rem; flex-shrink: 0; white-space: nowrap; }
@media (max-width: 640px) {
  html[data-profil="v33"] body #tr-content > .flex.items-center.border-b { column-gap: 0.5rem; padding-left: 4rem; }
  html[data-profil="v33"] body #tr-content > .flex.items-center.border-b > .w-8:first-child { margin-left: -3rem; }
}
/* L5. Ein elev som er i gang (raden har «Pågår...» under namnet) stod med «0% ✗» i raudt, som
   om han hadde fått 0. Til han er ferdig er poengsummen nøytral: inga statusfarge og ikkje
   ✓, ~ eller ✗. Teksten (poengsummen) er uendra. Utan :has() står raden som før. */
html[data-profil="v33"] body #tr-content > .flex.items-center.border-b:has(> .flex-1 > .text-blue-500) > :is(.bg-green-50, .bg-orange-50, .bg-red-50) { color: var(--pt-ink-secondary); background-color: var(--pt-surface-soft); }
html[data-profil="v33"] body #tr-content > .flex.items-center.border-b:has(> .flex-1 > .text-blue-500) > :is(.bg-green-50, .bg-orange-50, .bg-red-50)::after { content: none; }
/* L3. Bonusknappen blir «✓» når læraren har gjeve eit ekstra forsøk, rett ved «96% ✓»: to hakar
   med ulik tyding. Den inaktive knappen viser «+1 ✓» (forsøket er gjeve). «+1» er berre
   synleg: knappen får namnet sitt frå aria-label i teacher-class-detail.js (i18n
   «tr_bonus_gitt», no/nn/en; Geir 22.10), så alternativteksten her er tom. */
html[data-profil="v33"] body #tr-content .tr-bonus-btn:disabled::before { content: "+1 "; content: "+1 " / ""; }
/* L11. Klagekøen på ein låg telefon (375×667): toppen, handlingsbandet og fotlina i
   resultatdialogen stod fast, og lista mellom dei fekk 167 px (69 px på 320×568). «Godkjenn» og
   «Avvis» låg under folda i den vesle rulleboksen. På låge skjermar har kortet inga høgdegrense:
   heile dialogen rullar i overlegget (som «Opprett gloseprøve»), og køen står rett under
   handlingsbandet. Overlegget byrjar øvst; auto-marga sentrerer kortet når det er plass. Berre
   på telefon (smal og låg, eller låg i liggjande stilling): på ein laptop (om lag 650 px høgt
   vindauge) står topp og fotline fast som før, og lista rullar mellom dei. */
@media (max-width: 640px) and (max-height: 720px), (max-height: 480px) {
  html[data-profil="v33"] body #tcd-results-modal { align-items: flex-start; }
  html[data-profil="v33"] body #tcd-results-modal > div { max-height: none; margin-block: auto; }
}
/* L9. «Opprett gloseprøve»: avkryssingsboksane (w-4 h-4 i ein flex-etikett) vart klemde til 13 px
   breie av den lange teksten ved sida av, og stod 5 px over midten av første line (mt-0.5 var
   rekna for ei line på 20 px; med 18 px tekst er lina 27 px). Boksen krympar ikkje, og står midt
   på første line: (1,5rem − 1rem) / 2. Veljarane under «Maks forsøk» og «Utløper automatisk» står
   på same høgd sjølv når den eine etiketten går over to liner. */
html[data-profil="v33"] body #tcd-create-test-modal label.flex.items-start > input[type="checkbox"] { flex-shrink: 0; margin-top: 0.25rem; }
html[data-profil="v33"] body #tcd-create-test-modal .grid.grid-cols-2 { align-items: end; }

/* L8. Presentasjonsvisaren: baksida av ordkortet og fun fact-boksen er bg-amber-900 med
   bg-opacity (gjennomsiktig amber over den mørke scena utan profilen). Under profilen blei dei
   same mørke panel som framsida, så baksida såg ut som framsida, og fun fact var ei tung mørk
   blokk på den lyse scena. No er dei ei lys tintflate med aksentkant, mørk tekst og lenkjefarge
   på merkelappen («Tysk»): baksida skil seg frå framsida, og fun fact er ein merknad. */
html[data-profil="v33"] body[data-side="visar"] .bg-amber-900[class*="bg-opacity-"] { background-color: var(--pt-tint); color: var(--pt-ink); border-color: var(--pt-accent); }
html[data-profil="v33"] body[data-side="visar"] .bg-amber-900[class*="bg-opacity-"] .text-amber-400 { color: var(--pt-link); }
html[data-profil="v33"] body[data-side="visar"] .bg-amber-900[class*="bg-opacity-"] .text-amber-200 { color: var(--pt-heading); }
/* L12. Toppfeltet på 320 px tok fire liner (172 px av 700): tittelen på to, tastaturhintet og
   knappane. Til og med 640 px står tittelen i 1,125rem (éi line for «Leksjon 1.2 — Meine
   Familie»), og hintet («Trykk SPACE eller → for neste») er borte; det same på ein
   berøringsskjerm utan peikar som kan sveve (ingen tastatur å trykkje på). Tastane verkar
   framleis, og Forrige/Neste står i botnfeltet. Toppfeltet blir to liner: tittelen og knappane. */
@media (max-width: 640px) {
  html[data-profil="v33"] body[data-side="visar"] #pres-title { font-size: 1.125rem; }
  html[data-profil="v33"] body[data-side="visar"] > nav .flex.gap-4 > span:first-child { display: none; }
}
@media (hover: none) and (pointer: coarse) {
  html[data-profil="v33"] body[data-side="visar"] > nav .flex.gap-4 > span:first-child { display: none; }
}

/* L1. Samsvarssida: tabellane rullar sideveis i .section-inline til og med 640 px (fase 6), og
   ein boks som rullar, klipper alt som går ut over kanten hans. Overskriftene og merknadene i
   boksen (alt utanom tabellane) rulla med tabellen ut av synet, og lenkja i merknaden om
   informasjonskapslar stod utanfor boksen eller ved kanten når ho fekk fokus etter at tabellen
   var rulla (488–640 px): ringen var kutta, eller heile lenkja usynleg. No står dei fast ved
   venstrekanten medan tabellen rullar. Luft rundt innhaldet (padding) trengst ikkje: målt frå
   320 til 640 px blir ingen ring klipt utan ho, og tabellcellene har eiga luft (10 px). */
@media (max-width: 640px) {
  html[data-profil="v33"] body[data-side="samsvar"] .section-inline > :not(table) { position: sticky; left: 0; }
}
/* L2. Overskriftene på infosidene braut midt i ordet på 320 px («Personvernerkl/æring»,
   «Tilgjengelighets/erklæring»). Med hyphens: auto deler nettlesaren ordet etter staving og set
   bindestrek; det krev lang på <html>, som alle desse sidene har (404.html fekk lang="no" 17.10,
   Geir). I nettlesarar utan orddeling for norsk står overflow-wrap: break-word frå grunnlaget att. */
html[data-profil="v33"] body:is([data-side="personvern"], [data-side="vilkar"], [data-side="support"], [data-side="tilgjengelegheit"], [data-side="samsvar"], [data-side="proveperiode"], [data-side="404"]) :is(h1, h2, h3) { -webkit-hyphens: auto; hyphens: auto; }
/* L6. «Logg inn med Google» (proveperiode.html, kvit knapp på kvitt kort) hadde ein kant i
   --pt-border: 1,30:1 mot kortet i lys og 1,38:1 i mørk palett. Knappen er ei trykkflate, og
   kanten er det einaste som viser henne: same sterke kant som Apple-knappen (≥ 3:1 i begge). */
html[data-profil="v33"] body[data-side="proveperiode"] #google-login-btn { border-color: var(--pt-border-strong); }

@media (prefers-reduced-motion: reduce) {
  html[data-profil="v33"] body *,
  html[data-profil="v33"] body *::before,
  html[data-profil="v33"] body *::after {
    transition: none !important;
    animation: none !important;
  }
}

/* ── Seksjonsoverskriftene: ikon frå PaperTek-designprofilen (ikonbytte 19.10.2026) ──
   Erstattar plasshaldaren (generisk bokmaske på alle h2). Spesifikasjon
   2026-10-19-ikonbytte-design.md §6.1, §6.8, §7, §7b. Berre CSS: kvar overskrift har ein
   stabil krok data-pt-seksjon="…" (mal, generator og lastarane set han), og ::before teiknar
   SVG-fila som bakgrunn — aldri som innebygd markup (ein bakgrunn kan ikkje køyre skript).
   - Berre under v33-flagget: utan det finst ingen regel, og emoji-ane under står att som før.
   - Ikonet står i venstre kant av overskrifta (absolutt), og teksten har padding-venstre = ikon + gap,
     så teksten bryt BESIDE ikonet (spesifikasjon §7b), aldri under det. Ikkje flex/grid: overskrifter
     har fleire inline-barn (<span>, <em>, ordtaggar) som då blei kolonnar. padding-block fyller
     overskrifta opp til ikonhøgda (lh-eininga), så enkeltlinja er midtstilt mot ikonet.
   - Seksjonsoverskriftene er 64 px. Øvingskorta (data-pt-liten, sett av ovelse-ikon.js) har eit lite
     ikon på 32 px inline i overskrifta (tillegg §9 val 10: «som boka»; eit medvite unntak frå 64 px).
   - Utan plate eller bakgrunnsfarge. Lys fil står berre på lyse flater, mørk berre på
     --pt-surface (#0B3E44): dei tre mørke formene under byter fil, og @media print set lys fil
     attende (papiret er lyst). Kort som elles har ei tona flate får --pt-surface (sjå under).
   - Dekorativt: tom alt-tekst på ::before, og teksten står ved sida av.
   - «Husk!» er berre i boka (§7b), så han har ingen krok her. */
html[data-profil="v33"] body [data-pt-seksjon] {
  --pt-sik-storleik: 64px;
  --pt-sik-gap: 0.75rem;
  position: relative;
  padding-left: calc(var(--pt-sik-storleik) + var(--pt-sik-gap));
  padding-block: 0.75rem;
  padding-block: max(0px, calc((var(--pt-sik-storleik) - 1lh) / 2));
}
html[data-profil="v33"] body [data-pt-seksjon][data-pt-liten] {
  --pt-sik-storleik: 32px;
  --pt-sik-gap: 0.5rem;
}
/* Smal skjerm (320 px): 64 px ikon + tekst beside lèt berre ~150 px til teksten, og «Læringsmål»
   i 27 px er like breitt. Overskriftene med ikon går ned til 1.125rem (20,25 px på 18 px-rota) og litt mindre gap, så eit ord
   ikkje blir kutta midt i (overflow-wrap: break-word frå grunnlaget er siste utveg). */
@media (max-width: 400px) {
  html[data-profil="v33"] body [data-pt-seksjon]:not([data-pt-liten]) { --pt-sik-gap: 0.5rem; }
  html[data-profil="v33"] body [data-pt-seksjon] { font-size: 1.125rem; }
}
html[data-profil="v33"] body [data-pt-seksjon]::before {
  content: "";
  content: "" / "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: var(--pt-sik-storleik);
  height: var(--pt-sik-storleik);
  background-image: var(--pt-sik-lys);
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
}
html[data-profil="v33"] body [data-pt-seksjon="maal"] { --pt-sik-lys: url("/ikon/papertek_reading_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_reading_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="lesetekst"] { --pt-sik-lys: url("/ikon/papertek_reading_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_reading_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="dialog"] { --pt-sik-lys: url("/ikon/papertek_dialog_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_dialog_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="ordforrad"] { --pt-sik-lys: url("/ikon/papertek_ordbok_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_ordbok_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="ovglosene"] { --pt-sik-lys: url("/ikon/papertek_ordjakt_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_ordjakt_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="grammatikk"] { --pt-sik-lys: url("/ikon/papertek_grammatikk_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_grammatikk_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="uttale"] { --pt-sik-lys: url("/ikon/papertek_opplesing_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_opplesing_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="kultur"] { --pt-sik-lys: url("/ikon/papertek_kulturhjornet_light_R3.svg"); --pt-sik-mork: url("/ikon/papertek_kulturhjornet_dark_R3.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="ovelser"] { --pt-sik-lys: url("/ikon/papertek_tasks_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_tasks_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="repetisjon"] { --pt-sik-lys: url("/ikon/papertek_repetisjon_light_R3.svg"); --pt-sik-mork: url("/ikon/papertek_repetisjon_dark_R3.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="ekspert"] { --pt-sik-lys: url("/ikon/papertek_mini_ekstraoppgaver_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_mini_ekstraoppgaver_dark_R4.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="skriving"] { --pt-sik-lys: url("/ikon/papertek_writing_light_R2.svg"); --pt-sik-mork: url("/ikon/papertek_writing_dark_R2.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="laert"] { --pt-sik-lys: url("/ikon/papertek_naa_kan_jeg_light_R3.svg"); --pt-sik-mork: url("/ikon/papertek_naa_kan_jeg_dark_R3.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="laerar"] { --pt-sik-lys: url("/ikon/papertek_laerer_light_R3.svg"); --pt-sik-mork: url("/ikon/papertek_laerer_dark_R3.svg"); }
html[data-profil="v33"] body [data-pt-seksjon="aktivitetar"] { --pt-sik-lys: url("/ikon/papertek_spill_laering_light_R1.svg"); --pt-sik-mork: url("/ikon/papertek_spill_laering_dark_R1.svg"); }

@media (prefers-color-scheme: dark) {
  html[data-profil="v33"]:where(:not([data-tema="lys"])) body [data-pt-seksjon]::before { background-image: var(--pt-sik-mork); }
}
html[data-profil="v33"]:where([data-tema="mork"]) body [data-pt-seksjon]::before { background-image: var(--pt-sik-mork); }
@media print {
  html[data-profil="v33"] body [data-pt-seksjon]::before { background-image: var(--pt-sik-lys); }
}

/* Emoji som designprofilen byter ut ligg i <span class="pt-emoji-ut"> og blir berre skjult her. */
html[data-profil="v33"] .pt-emoji-ut { display: none; }

/* Tekst som berre høyrer til under v33 (t.d. «poeng» ved sidan av eit ikon). `hidden` er
   standard, så sider som ikkje lastar denne fila aldri viser han; under v33 blir han synleg. */
html[data-profil="v33"] .pt-berre-v33[hidden] { display: inline; }

/* Ikona står berre på --pt-surface (§6.8, §7b). Desse korta har elles ei tona flate (lesetekst-korta
   med teksttypefarge, sti-korta, faktaboksen, klasseromshovudet), så under v33 blir flata
   --pt-surface; typen viser seg framleis i kanten og merkelappen. */
html[data-profil="v33"] body :is([data-pt-ikonkort], .faktaboks, .ekstra-path-card, .ekstra-path-card:hover) { background: var(--pt-surface); }
/* Ordtrenaren (ikon-restar, oppgåve 8): ikona som står i ein liten eigen boks på ei tona flate. Boksen har
   berre ei flate under v33 (flagget av er klassen utan effekt, så teksten og emojien står som før).
   - .pt-synk-ikon: ikonet i synkmeldinga (#sync-status). Meldinga sjølv er tona (blå/grøn/raud), så berre ikonet
     får --pt-surface. 2 px luft held boksen (24 px) under tekstlinja, så høgda til meldinga (S13) ikkje veks.
   - .pt-blitz-ikon: edu-blitz ved sida av «Blitz-modus (60s)» (fylt primærknapp, T6) og «Blitz Fullført!» (tona flate). */
html[data-profil="v33"] body .pt-synk-ikon { display: inline-flex; align-items: center; justify-content: center; padding: 2px; border-radius: 0.5rem; }
/* Sky-knappen (auth-cloud.js, 20.10.2026): knappen er sin eigen ikon-boks (data-pt-ikonkort → --pt-surface), så tilstandsfargen
   (grøn/gul/raud/blå via text-*-klassene) bles ut av flata. Han står att i kanten, i tillegg til merkelappen og tittelen. */
html[data-profil="v33"] body [data-auth-cloud][data-pt-ikonkort] { border: 2px solid currentColor; }
/* Svarmerka ✓ / ✗ (emojiUtMerke, 20.10.2026) på ei tona flate: merket er sin eigen ikon-boks (--pt-surface via
   data-pt-ikonkort), same form som .pt-synk-ikon. Flagget av: klassen er utan stil. */
html[data-profil="v33"] body .pt-merke-ikon { display: inline-flex; align-items: center; justify-content: center; padding: 2px; border-radius: 0.5rem; vertical-align: middle; }
/* Nettlesarsjekk 20.10: det indre elementet (blir flex-element, med snurringa på seg) fekk ei tekstlinje (28,8 px) rundt
   det inline 20 px-ikonet, og meldinga vart 51 px høg mot 40 px med flagget av. line-height: 0 held boksen på 24 px. */
html[data-profil="v33"] body .pt-synk-ikon > span { display: flex; line-height: 0; }
/* Låst kapittel-overskrift (hub): overskrifta står rett på sida (--pt-bg, i mørk modus #062B30), og mørk fil står berre på
   --pt-surface (#0B3E44). Ikonet får difor ein eigen ikonboks (data-pt-ikonkort). Flagget av: spannet er utan stil. */
html[data-profil="v33"] body .pt-laas-ikon { display: inline-flex; align-items: center; justify-content: center; padding: 0.25rem; margin-right: 0.5rem; border-radius: 0.5rem; vertical-align: middle; }
html[data-profil="v33"] body .pt-blitz-ikon { display: inline-flex; align-items: center; justify-content: center; padding: 0.25rem; border-radius: 0.5rem; vertical-align: middle; }
/* Nettlesarsjekk 20.10 (ikon-restar, oppgåve 9), 320 px:
   - Rangliste-radene (hub): kallenamnet er ein <span class="truncate">, og ein inline-span ignorerer
     overflow/ellipsis, så eit langt namn dytta «N poeng N dager» ut av kortet og sida fekk vassrett rulling.
     Som inline-block med maks 100 % kuttar namnet seg (…) og talkolonna held plassen sin.
   - SR-mester (Profil): 64 px-ikonet + tittelblokka + poengpillen er breiare enn 248 px, så pillen stakk ut
     12 px. Hovudet får bryte, og pillen legg seg då under, til høgre. */
html[data-profil="v33"] #community-leaderboard-list .truncate { display: inline-block; max-width: 100%; vertical-align: bottom; }
@media (max-width: 400px) {
  /* Namnet får brytast på to-tre linjer i staden for «Te…» når talkolonna tek halve raden. */
  html[data-profil="v33"] #community-leaderboard-list .truncate { white-space: normal; overflow-wrap: anywhere; text-overflow: clip; }
}
/* Same sjekk: «1240 poeng 123 dager» ved sida av namnet tok heile raden på 320 px, så kallenamnet vart
   0 px breitt (heilt borte, også «Test Elev»). På smale skjermar står poenga over rekkja, til høgre. */
@media (max-width: 400px) {
  html[data-profil="v33"] :is(#community-leaderboard-list, #group-lb-list) .text-right { display: flex; flex-direction: column; align-items: flex-end; }
  html[data-profil="v33"] :is(#community-leaderboard-list, #group-lb-list) .text-right > .ml-2 { margin-left: 0; }
  /* Klasse-ranglista (rad: rang + namn til venstre, «N dager» + «N lp» til høgre): same stabling. */
  html[data-profil="v33"] [data-pt-lbtal] { flex-direction: column; align-items: flex-end; gap: 0.125rem; }
}
html[data-profil="v33"] [data-pt-sr-hovud] { flex-wrap: wrap; gap: 0.75rem; }
html[data-profil="v33"] [data-pt-sr-hovud] > :last-child { margin-left: auto; }
/* Verktøykorta på Leksjoner (shell.js createToolCard): ikonet er 64 px og tek plass frå titteltekstane.
   På 320 px blir kortet litt tettare (padding og gap), så «Grammatisk Ordliste» ikkje brekk midt i ordet;
   same breidde på tekstkolonna som før ikonbytet. */
@media (max-width: 400px) {
  html[data-profil="v33"] body [data-verktoykort] { padding: 1rem; }
  html[data-profil="v33"] body [data-verktoykort] > .flex { gap: 0.75rem; }
}
html[data-profil="v33"] body .faktaboks { border-color: var(--pt-border-strong); }
html[data-profil="v33"] body .faktaboks-summary { color: var(--pt-heading); }
html[data-profil="v33"] body .faktaboks-summary:hover { background: var(--pt-tint); }
html[data-profil="v33"] body .faktaboks-chevron { color: var(--pt-accent); }
html[data-profil="v33"] body .faktaboks-body li { color: var(--pt-ink); }
/* Ikon-berarar som ikkje er overskrifter: ikonet står i flyten (ikkje absolutt), utan padding.
   Faktaboksen er ei flex-rad (ikonet er eit eige element); stikorta har ikonet over teksten. */
html[data-profil="v33"] body :is(.faktaboks-icon, .ekstra-path-card [data-pt-seksjon]) { padding: 0; }
html[data-profil="v33"] body :is(.faktaboks-icon, .ekstra-path-card [data-pt-seksjon])::before {
  position: static;
  display: block;
  transform: none;
}

/* Plasshaldar for figurane ved dialogen — berre på breie skjermar, aldri over
   innhaldet. Nøytral merkelapp som standard; namna gjeld berre tysken (sjå under):
   spansk har Sofia og Lucas, fransk fleire figurar. */
@media (min-width: 768px) {
  :where(html[data-profil="v33"] body) div:has(> h2 > #dialog-tittel) { position: relative; }
  /* Merkelappen er tekst og står i 18 px med linjehøgd 1,5 (fase 7; var 0,75rem og 1,3).
     «Hovedpersonene» er om lag 133 px i 18 px Atkinson, så boksen er 9rem brei, og tittelen
     held avstand til han. */
  :where(html[data-profil="v33"] body) h2:has(> #dialog-tittel) { padding-right: 10.5rem; min-height: 96px; }
  :where(html[data-profil="v33"] body) h2:has(> #dialog-tittel)::after {
    content: "Hovedpersonene";
    content: "Hovedpersonene" / "";
    position: absolute;
    top: 1.5rem;
    right: 1.5rem;
    width: 9rem;
    height: 96px;
    box-sizing: border-box;
    padding-inline: 0.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    border: 2px dashed var(--pt-border-strong);
    border-radius: 12px;
    color: var(--pt-ink-secondary);
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
  }
  :where(html[data-profil="v33"] body:is([data-curriculum-id^="tysk"], [data-curriculum-id^="us-"])) h2:has(> #dialog-tittel)::after {
    content: "Lukas og Olivia";
    content: "Lukas og Olivia" / "";
  }
}

/* ═══ DESIGNPROFIL-IKON (spesifikasjon 2026-10-19-ikonbytte-design.md) ═══════
   Markupen kjem frå js/ikon/ikon.js (ikonHtml):
     <span class="pt-ikon pt-ikon--har-mork|--utan-mork" hidden style="--pt-ikon-storleik:Npx">
       <img class="pt-ikon__lys"><img class="pt-ikon__mork">
     </span><span class="pt-gammalt-ikon">dagens ikon</span>
   Flagget av: berre det gamle ikonet — appen ser ut som i dag. Omslaget har `hidden`, og
   ingen regel utan flagget trengst: sider som ikkje lastar denne fila (international, velg,
   verbtrener …) viser då heller aldri to ikon. Under flagget slår display:inline-flex
   (0,2,1) over `[hidden]` frå nettlesaren og Tailwind-preflight (0,1,0, utan !important).
   Flagget på: designprofil-ikonet. Mørk modus byter til mørk fil (same to former som
   token-blokkene øvst: «Følg enheten» i media-spørjinga, «Mørk» som tvilling under).
   Ikon utan godkjend mørk versjon (UI Essentials) gir plassen attende til det gamle.
   Ingen bakgrunn eller plate: designprofilen forbyr kvit boks. */
html[data-profil="v33"] .pt-gammalt-ikon { display: none; }
html[data-profil="v33"] .pt-ikon {
  display: inline-flex;
  flex: none;
  width: var(--pt-ikon-storleik);
  height: var(--pt-ikon-storleik);
  vertical-align: middle;
}
/* Ingen display her: regelen har tyngd (0,2,2) og ville slått gøyminga av .pt-ikon__mork
   (0,2,1, display: none), så lys modus viste begge filene. Bileta er flex-element i omslaget
   og blir blokk utan eigen regel. */
html[data-profil="v33"] .pt-ikon img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
html[data-profil="v33"] .pt-ikon__mork { display: none; }

@media (prefers-color-scheme: dark) {
  /* Tvillingane står rett under: tests/unit/fargetema-css.test.js */
  html[data-profil="v33"]:where(:not([data-tema="lys"])) .pt-ikon__mork { display: block; }
  html[data-profil="v33"]:where(:not([data-tema="lys"])) .pt-ikon--har-mork .pt-ikon__lys { display: none; }
  html[data-profil="v33"]:where(:not([data-tema="lys"])) .pt-ikon--utan-mork { display: none; }
  html[data-profil="v33"]:where(:not([data-tema="lys"])) .pt-ikon--utan-mork + .pt-gammalt-ikon { display: contents; }
}
html[data-profil="v33"]:where([data-tema="mork"]) .pt-ikon__mork { display: block; }
html[data-profil="v33"]:where([data-tema="mork"]) .pt-ikon--har-mork .pt-ikon__lys { display: none; }
html[data-profil="v33"]:where([data-tema="mork"]) .pt-ikon--utan-mork { display: none; }
html[data-profil="v33"]:where([data-tema="mork"]) .pt-ikon--utan-mork + .pt-gammalt-ikon { display: contents; }

/* Utskrift: papiret er lyst (som token-blokka over), så lys versjon og designprofil-ikonet
   vinn over begge mørke formene. Høgare tyngd enn dei, og står etter dei. */
@media print {
  html[data-profil="v33"] .pt-ikon .pt-ikon__mork { display: none; }
  html[data-profil="v33"] .pt-ikon.pt-ikon--har-mork .pt-ikon__lys { display: block; }
  html[data-profil="v33"] .pt-ikon.pt-ikon--utan-mork { display: inline-flex; }
  html[data-profil="v33"] .pt-ikon--utan-mork + .pt-gammalt-ikon { display: none; }
}

/* ── Status på designprofil-ikona (spesifikasjon 2026-10-19-ikonbytte-design.md §6.10, val 9) ──
   Klassane kjem frå js/ikon/ikon-status.js og står på .pt-ikon-omslaget:
   - pt-ikon--uferdig: ikkje ferdig / inaktiv fane. Ikonet blir blekna — BERRE opacity. Fila blir
     aldri omfarga (designprofilen forbyr det), og ingen filter. 0,55 held 3:1 (eigarregelen for
     ikon, WCAG 1.4.11): den mørkaste streken i kvar fil blanda med flata gir minst 3,17:1 på
     #FFFFFF (rangliste Small) og 4,19:1 på #0B3E44 (keyline #E8F3B6). 0,35 gav berre 2,0 og 2,6.
     tests/unit/ikon-status.test.js reknar det ut frå filene.
   - pt-ikon--niva-1…4: blyant-/stjernenivået som ein prikk nede til høgre i nivåfargen
     (--pt-blyant-*, dei same fire som pt-niva-N over, med 3:1 mot flatene). Ein tynn ring i
     --pt-surface skil prikken frå ikonet. Nivåteksten (title) står som før, så fargen åleine ber
     aldri meininga.
   Ferdig/aktiv utan nivå: ingen klasse, full farge. Berre under v33: flagget av viser dagens ikon. */
html[data-profil="v33"] .pt-ikon.pt-ikon--uferdig { opacity: 0.55; }
html[data-profil="v33"] .pt-ikon--niva-1 { --pt-ikon-niva: var(--pt-blyant-gronn); }
html[data-profil="v33"] .pt-ikon--niva-2 { --pt-ikon-niva: var(--pt-blyant-bla); }
html[data-profil="v33"] .pt-ikon--niva-3 { --pt-ikon-niva: var(--pt-blyant-rubin); }
html[data-profil="v33"] .pt-ikon--niva-4 { --pt-ikon-niva: var(--pt-blyant-gull); }
html[data-profil="v33"] .pt-ikon:is(.pt-ikon--niva-1, .pt-ikon--niva-2, .pt-ikon--niva-3, .pt-ikon--niva-4) { position: relative; }
html[data-profil="v33"] .pt-ikon:is(.pt-ikon--niva-1, .pt-ikon--niva-2, .pt-ikon--niva-3, .pt-ikon--niva-4)::after {
  content: "";
  content: "" / "";
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: max(9px, calc(var(--pt-ikon-storleik) * 0.3));
  height: max(9px, calc(var(--pt-ikon-storleik) * 0.3));
  border-radius: 50%;
  background-color: var(--pt-ikon-niva);
  box-shadow: 0 0 0 2px var(--pt-surface);
}

/* Ordtrenaren: korta var --pt-bg (bg-stone-50) og er no --pt-surface (data-pt-ikonkort), same farge
   som sida rundt i lys modus. Ein tynn kant held kortet synleg, som korta elles i profilen. */
html[data-profil="v33"] body #training-modes [data-pt-ikonkort] { border: 1px solid var(--pt-border); }
/* Rangliste: rang 1 har ikonet Ukens mester (64 px) i ein kolonne som elles er w-8 (#2, 🥈 …). */
html[data-profil="v33"] body [data-pt-rangikon] { width: auto; }

/* UI Essentials-ikon (lyse, kun på #FFFFFF/#FAFCFB): avslutt-knappane i øvingane er runde skiver med
   `bg-white/80`, som regelen over gjer om til --pt-tint (#EEF5F3). Ikonet skal ikkje liggje på ein tona
   flate, så skiva blir --pt-surface (kvit i lys modus; i mørk modus står det gamle ikonet på --pt-surface). */
html[data-profil="v33"] body :is(#exit-vocab-test-btn, #exit-verb-test-btn, #exit-skriv-btn) { background-color: var(--pt-surface); }
