Compare commits
3 Commits
9a7a7b9ef1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b5a96d276 | |||
| 0f4370626c | |||
| 3f7f5d86b1 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -20,6 +20,10 @@ package.json
|
|||||||
# App localStorage tilstand (lagres pr nettleser)
|
# App localStorage tilstand (lagres pr nettleser)
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
|
# app/notes opprettes av launcherne per plattform (symlink på unix, kopi på Windows).
|
||||||
|
# Committes IKKE — git-symlinks materialiseres som ødelagte tekstfiler på Windows.
|
||||||
|
/app/notes
|
||||||
|
|
||||||
# Verifikasjons-skjermbilder
|
# Verifikasjons-skjermbilder
|
||||||
/screenshots/
|
/screenshots/
|
||||||
.claude/
|
.claude/
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ Bygget til eksamen mandag **1. juni 2026**, men generelt nyttig for faget.
|
|||||||
|
|
||||||
## Hva får du
|
## Hva får du
|
||||||
|
|
||||||
|
- **Fast-track** — hele pensum kondensert til 5 moduler etter eksamensstrukturen, gjentakelsesfritt, med huskeregler, eksempler og «eksamensfeller». Egen fremdriftsmåler (lest-markering lagres lokalt)
|
||||||
- **Sammendrag** av alle 12 forelesninger som lesbare sider
|
- **Sammendrag** av alle 12 forelesninger som lesbare sider
|
||||||
- **120 flashcards** med flip-animasjon, kategori-filter og «glemt/ok/kunne»-markering
|
- **150 flashcards** med flip-animasjon, kategori-filter og «glemt/ok/kunne»-markering — inkl. et eget **Fast-track-sett** (30 konsise kort som tester huskereglene og eksamensfellene; nås direkte fra Fast-track-siden eller via `#/flashcards/fasttrack`)
|
||||||
- **49 quiz-spørsmål** med umiddelbar feedback og forklaringer
|
- **49 quiz-spørsmål** med umiddelbar feedback og forklaringer
|
||||||
- **16 eksamenstrener-oppgaver** med sjekkliste, veiledet svar og tips
|
- **16 eksamenstrener-oppgaver** med sjekkliste, veiledet svar og tips
|
||||||
- **tl;dr** — det aller viktigste destillert til én side (for siste-minutts pugging på bussen)
|
- **tl;dr** — det aller viktigste destillert til én side (for siste-minutts pugging på bussen)
|
||||||
@@ -58,7 +59,7 @@ SMF/
|
|||||||
│ ├── data/ # JSON: flashcards (120), quiz (49), exam (16)
|
│ ├── data/ # JSON: flashcards (120), quiz (49), exam (16)
|
||||||
│ ├── notes/ # Symlink til ../notes
|
│ ├── notes/ # Symlink til ../notes
|
||||||
│ └── vendor/ # marked.min.js (markdown-renderer)
|
│ └── vendor/ # marked.min.js (markdown-renderer)
|
||||||
├── notes/ # Markdown-sammendrag per uke + tldr.md
|
├── notes/ # Markdown-sammendrag per uke + tldr.md + fast-track.md
|
||||||
├── pdf/ # PDF-versjoner av forelesningene
|
├── pdf/ # PDF-versjoner av forelesningene
|
||||||
└── *.pptx # Originale PowerPoints fra Martina
|
└── *.pptx # Originale PowerPoints fra Martina
|
||||||
```
|
```
|
||||||
|
|||||||
44
Start.bat
44
Start.bat
@@ -120,19 +120,24 @@ if not exist "%VENDOR_DIR%\marked.min.js" (
|
|||||||
echo [v] marked.js OK
|
echo [v] marked.js OK
|
||||||
)
|
)
|
||||||
|
|
||||||
rem --- Verify notes/ exists in app/ ------------------------------------
|
rem --- Ensure app\notes is a real directory with current notes --------
|
||||||
if not exist "%APP_DIR%\notes\uke17-eksamen.md" (
|
rem Git lagrer app/notes som en symlink. Pa Windows uten symlink-stotte
|
||||||
echo [.] Notes mangler i app/ - kopierer ...
|
rem materialiseres den som en STRAY TEKSTFIL (innhold: "../notes"), som
|
||||||
if exist "%APP_DIR%\notes" rmdir /s /q "%APP_DIR%\notes" 2>nul
|
rem bryter appen. Vi normaliserer alltid: fjern fil, lag mappe, kopier.
|
||||||
mkdir "%APP_DIR%\notes" 2>nul
|
rem ("if exist sti\" med etterfolgende backslash er sant kun for mapper.)
|
||||||
xcopy /Y /Q "%SCRIPT_DIR%notes\*.md" "%APP_DIR%\notes\" >nul
|
if exist "%APP_DIR%\notes" if not exist "%APP_DIR%\notes\" (
|
||||||
if exist "%APP_DIR%\notes\uke17-eksamen.md" (
|
echo [.] Fjerner ugyldig notes-fil ^(git-symlink pa Windows^) ...
|
||||||
echo [v] Notes kopiert
|
del /f /q "%APP_DIR%\notes" >nul 2>&1
|
||||||
) else (
|
)
|
||||||
echo [x] Klarte ikke kopiere notes/
|
if not exist "%APP_DIR%\notes\" mkdir "%APP_DIR%\notes" >nul 2>&1
|
||||||
pause
|
xcopy /Y /Q "%SCRIPT_DIR%notes\*.md" "%APP_DIR%\notes\" >nul 2>&1
|
||||||
exit /b 1
|
if exist "%APP_DIR%\notes\fast-track.md" (
|
||||||
)
|
echo [v] Notes OK
|
||||||
|
) else (
|
||||||
|
echo [x] Klarte ikke kopiere notes/ fra "%SCRIPT_DIR%notes"
|
||||||
|
echo Sjekk at notes-mappen finnes i prosjektroten.
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
rem --- Find a free port -----------------------------------------------
|
rem --- Find a free port -----------------------------------------------
|
||||||
@@ -168,5 +173,18 @@ start "" /min cmd /c "timeout /t 2 >nul & start http://localhost:%PORT%"
|
|||||||
rem --- Start server ----------------------------------------------------
|
rem --- Start server ----------------------------------------------------
|
||||||
cd /d "%APP_DIR%"
|
cd /d "%APP_DIR%"
|
||||||
%SERVER_CMD%
|
%SERVER_CMD%
|
||||||
|
set "SERVER_EXIT=%errorlevel%"
|
||||||
|
|
||||||
|
rem --- Server stoppet: hold vinduet apent sa feil kan leses -----------
|
||||||
|
echo.
|
||||||
|
if not "%SERVER_EXIT%"=="0" (
|
||||||
|
echo [x] Serveren avsluttet med feilkode %SERVER_EXIT%.
|
||||||
|
echo Les meldingen over. Vanlige arsaker: porten var opptatt,
|
||||||
|
echo eller runtime ^(%SERVER_NAME%^) mangler rettigheter.
|
||||||
|
) else (
|
||||||
|
echo Serveren ble stoppet.
|
||||||
|
)
|
||||||
|
echo Trykk en tast for a lukke vinduet ...
|
||||||
|
pause >nul
|
||||||
|
|
||||||
endlocal
|
endlocal
|
||||||
|
|||||||
6
Start.sh
6
Start.sh
@@ -177,10 +177,14 @@ for f in "${required_files[@]}"; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Notes-mappen er en symlink — sjekk at den peker rett
|
# app/notes opprettes per plattform (gitignorert). Den skal være en symlink
|
||||||
|
# til ../notes. Håndter ødelagt symlink ELLER en git-materialisert tekstfil.
|
||||||
if [ -L "$APP_DIR/notes" ] && [ ! -e "$APP_DIR/notes" ]; then
|
if [ -L "$APP_DIR/notes" ] && [ ! -e "$APP_DIR/notes" ]; then
|
||||||
warn "notes-symlink er ødelagt — gjenoppretter …"
|
warn "notes-symlink er ødelagt — gjenoppretter …"
|
||||||
rm -f "$APP_DIR/notes"
|
rm -f "$APP_DIR/notes"
|
||||||
|
elif [ -f "$APP_DIR/notes" ]; then
|
||||||
|
warn "app/notes er en vanlig fil (git-symlink fra Windows) — erstatter med symlink …"
|
||||||
|
rm -f "$APP_DIR/notes"
|
||||||
fi
|
fi
|
||||||
if [ ! -d "$APP_DIR/notes" ]; then
|
if [ ! -d "$APP_DIR/notes" ]; then
|
||||||
if [ -d "$SCRIPT_DIR/notes" ]; then
|
if [ -d "$SCRIPT_DIR/notes" ]; then
|
||||||
|
|||||||
@@ -1935,3 +1935,356 @@ blockquote {
|
|||||||
.app { grid-template-columns: 1fr; }
|
.app { grid-template-columns: 1fr; }
|
||||||
.canvas { padding: 0; }
|
.canvas { padding: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===================================================
|
||||||
|
Fast-track — kondensert læringsspor
|
||||||
|
=================================================== */
|
||||||
|
.sidebar__link--fasttrack .sidebar__link-num {
|
||||||
|
color: var(--accent-2);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hero */
|
||||||
|
.ft-hero {
|
||||||
|
padding: var(--sp-7) 0 var(--sp-6);
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
margin-bottom: var(--sp-7);
|
||||||
|
}
|
||||||
|
.ft-hero__badge {
|
||||||
|
display: inline-block;
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-0);
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent-2);
|
||||||
|
border: 1px solid var(--line-strong);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 4px 10px;
|
||||||
|
margin-bottom: var(--sp-4);
|
||||||
|
}
|
||||||
|
.ft-hero__title {
|
||||||
|
font-family: var(--f-display);
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: var(--s-7);
|
||||||
|
line-height: 1.05;
|
||||||
|
color: var(--ink);
|
||||||
|
margin-bottom: var(--sp-4);
|
||||||
|
}
|
||||||
|
.ft-hero__title em { font-style: italic; color: var(--accent-2); }
|
||||||
|
.ft-hero__sub {
|
||||||
|
font-size: var(--s-3);
|
||||||
|
line-height: 1.6;
|
||||||
|
color: var(--ink-2);
|
||||||
|
max-width: 60ch;
|
||||||
|
}
|
||||||
|
.ft-hero__sub strong { color: var(--ink); }
|
||||||
|
|
||||||
|
/* Progress */
|
||||||
|
.ft-progress { margin-top: var(--sp-6); max-width: 480px; }
|
||||||
|
.ft-progress__head {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
margin-bottom: var(--sp-2);
|
||||||
|
}
|
||||||
|
.ft-progress__label {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-0);
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
.ft-progress__count {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-1);
|
||||||
|
color: var(--accent-2);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
.ft-progress__track {
|
||||||
|
height: 6px;
|
||||||
|
background: var(--surface-2);
|
||||||
|
border-radius: 99px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.ft-progress__bar {
|
||||||
|
height: 100%;
|
||||||
|
width: 0;
|
||||||
|
background: linear-gradient(90deg, var(--accent-2), var(--accent));
|
||||||
|
border-radius: 99px;
|
||||||
|
transition: width 0.6s var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Module grid */
|
||||||
|
.ft-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||||
|
gap: var(--sp-4);
|
||||||
|
}
|
||||||
|
.ft-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: var(--sp-5);
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-top: 3px solid var(--ft-color, var(--accent));
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
transition: transform 0.25s var(--ease), border-color 0.25s, background 0.25s;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.ft-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
background: var(--surface-2);
|
||||||
|
}
|
||||||
|
.ft-card__top {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: var(--sp-3);
|
||||||
|
}
|
||||||
|
.ft-card__num {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-4);
|
||||||
|
color: var(--ft-color, var(--accent));
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
.ft-card__check {
|
||||||
|
width: 22px; height: 22px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1.5px solid var(--line-strong);
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
font-size: var(--s-0);
|
||||||
|
color: transparent;
|
||||||
|
transition: all 0.25s;
|
||||||
|
}
|
||||||
|
.ft-card--done .ft-card__check {
|
||||||
|
background: var(--ft-color, var(--accent));
|
||||||
|
border-color: var(--ft-color, var(--accent));
|
||||||
|
color: var(--bg);
|
||||||
|
}
|
||||||
|
.ft-card__eyebrow {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-0);
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.ft-card__title {
|
||||||
|
font-family: var(--f-display);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: var(--s-5);
|
||||||
|
line-height: 1.15;
|
||||||
|
color: var(--ink);
|
||||||
|
margin-bottom: var(--sp-3);
|
||||||
|
}
|
||||||
|
.ft-card__desc {
|
||||||
|
font-size: var(--s-1);
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--ink-2);
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: var(--sp-4);
|
||||||
|
}
|
||||||
|
.ft-card__foot {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: var(--sp-3);
|
||||||
|
border-top: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
.ft-card__mins {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-0);
|
||||||
|
color: var(--subtle);
|
||||||
|
}
|
||||||
|
.ft-card__arrow {
|
||||||
|
font-size: var(--s-1);
|
||||||
|
color: var(--ft-color, var(--accent));
|
||||||
|
font-weight: 500;
|
||||||
|
transition: transform 0.2s var(--ease);
|
||||||
|
}
|
||||||
|
.ft-card:hover .ft-card__arrow { transform: translateX(5px); }
|
||||||
|
|
||||||
|
/* Mark-as-read button */
|
||||||
|
.ft-done-btn {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-0);
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--line-strong);
|
||||||
|
border-radius: 99px;
|
||||||
|
padding: 6px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.ft-done-btn:hover { color: var(--ink); border-color: var(--ink-2); }
|
||||||
|
.ft-done-btn--active {
|
||||||
|
color: var(--bg);
|
||||||
|
background: var(--accent-2);
|
||||||
|
border-color: var(--accent-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Module body callouts — passed through as raw HTML from markdown */
|
||||||
|
.ft-body .callout {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--sp-4);
|
||||||
|
margin: var(--sp-5) 0;
|
||||||
|
padding: var(--sp-4) var(--sp-5);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-left: 3px solid var(--accent);
|
||||||
|
font-size: var(--s-1);
|
||||||
|
line-height: 1.6;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.ft-body .callout > div { color: var(--ink-2); }
|
||||||
|
.ft-body .callout strong { color: var(--ink); }
|
||||||
|
.ft-body .callout__label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 700;
|
||||||
|
padding-top: 2px;
|
||||||
|
min-width: 7.5em;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.ft-body .callout--huske {
|
||||||
|
border-left-color: var(--accent-2);
|
||||||
|
background: color-mix(in srgb, var(--accent-2) 7%, var(--surface));
|
||||||
|
}
|
||||||
|
.ft-body .callout--huske .callout__label { color: var(--accent-2); }
|
||||||
|
.ft-body .callout--eksempel {
|
||||||
|
border-left-color: var(--theme-baerekraft);
|
||||||
|
background: color-mix(in srgb, var(--theme-baerekraft) 8%, var(--surface));
|
||||||
|
}
|
||||||
|
.ft-body .callout--eksempel .callout__label { color: var(--theme-baerekraft); }
|
||||||
|
.ft-body .callout--felle {
|
||||||
|
border-left-color: var(--accent);
|
||||||
|
background: color-mix(in srgb, var(--accent) 8%, var(--surface));
|
||||||
|
}
|
||||||
|
.ft-body .callout--felle .callout__label { color: var(--accent); }
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.ft-body .callout { flex-direction: column; gap: var(--sp-2); }
|
||||||
|
.ft-body .callout__label { min-width: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Home promo */
|
||||||
|
.ft-promo {
|
||||||
|
padding: var(--sp-7) 0;
|
||||||
|
border-top: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
.ft-promo__card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--sp-5);
|
||||||
|
padding: var(--sp-5) var(--sp-6);
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
transition: transform 0.25s var(--ease), background 0.25s, border-color 0.25s;
|
||||||
|
}
|
||||||
|
.ft-promo__card:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
background: var(--surface-2);
|
||||||
|
border-color: var(--line-strong);
|
||||||
|
}
|
||||||
|
.ft-promo__icon {
|
||||||
|
font-family: var(--f-display);
|
||||||
|
font-size: var(--s-8);
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--accent-2);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.ft-promo__body { flex: 1; }
|
||||||
|
.ft-promo__label {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-0);
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent-2);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.ft-promo__title {
|
||||||
|
font-family: var(--f-display);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: var(--s-5);
|
||||||
|
color: var(--ink);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.ft-promo__title em { font-style: italic; color: var(--accent-2); }
|
||||||
|
.ft-promo__desc {
|
||||||
|
font-size: var(--s-1);
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--ink-2);
|
||||||
|
max-width: 64ch;
|
||||||
|
}
|
||||||
|
.ft-promo__arrow {
|
||||||
|
font-size: var(--s-6);
|
||||||
|
color: var(--accent-2);
|
||||||
|
transition: transform 0.2s var(--ease);
|
||||||
|
}
|
||||||
|
.ft-promo__card:hover .ft-promo__arrow { transform: translateX(8px); }
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.ft-promo__card { flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
|
||||||
|
.ft-promo__arrow { align-self: flex-end; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fast-track: test-CTA på landingssiden */
|
||||||
|
.ft-test {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: var(--sp-5);
|
||||||
|
margin-top: var(--sp-7);
|
||||||
|
padding: var(--sp-5) var(--sp-6);
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-left: 3px solid var(--accent-2);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
}
|
||||||
|
.ft-test__label {
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-0);
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent-2);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.ft-test__title {
|
||||||
|
font-family: var(--f-display);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: var(--s-5);
|
||||||
|
color: var(--ink);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.ft-test__title em { font-style: italic; color: var(--accent-2); }
|
||||||
|
.ft-test__desc {
|
||||||
|
font-size: var(--s-1);
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--ink-2);
|
||||||
|
max-width: 56ch;
|
||||||
|
}
|
||||||
|
.ft-test__cta {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-family: var(--f-mono);
|
||||||
|
font-size: var(--s-1);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
color: var(--bg);
|
||||||
|
background: var(--accent-2);
|
||||||
|
border-radius: 99px;
|
||||||
|
padding: 12px 22px;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: transform 0.2s var(--ease), filter 0.2s;
|
||||||
|
}
|
||||||
|
.ft-test__cta:hover { transform: translateX(4px); filter: brightness(1.08); }
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.ft-test { flex-direction: column; align-items: flex-start; }
|
||||||
|
.ft-test__cta { align-self: stretch; text-align: center; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -958,5 +958,215 @@
|
|||||||
"week": 8,
|
"week": 8,
|
||||||
"front": "Hvordan kobles eksternaliteter til Brundtlands bærekraftdefinisjon?",
|
"front": "Hvordan kobles eksternaliteter til Brundtlands bærekraftdefinisjon?",
|
||||||
"back": "Negative eksternaliteter (klimagassutslipp, forurensning) er det operative bærekraftproblemet. Brundtlands definisjon krever at vi internaliserer disse – ellers ødelegger vi for fremtidige generasjoner. CSR = ta ansvar for negative eksternaliteter."
|
"back": "Negative eksternaliteter (klimagassutslipp, forurensning) er det operative bærekraftproblemet. Brundtlands definisjon krever at vi internaliserer disse – ellers ødelegger vi for fremtidige generasjoner. CSR = ta ansvar for negative eksternaliteter."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-001",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 1 · Etikk",
|
||||||
|
"front": "Etikk vs. moral vs. jus — på tre ord?",
|
||||||
|
"back": "<strong>Etikk = teori</strong> (systematisk refleksjon, et fag). <strong>Moral = praksis</strong> (praktiserte normer). <strong>Jus = paragraf</strong> (formelt regelverk håndhevet av staten)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-002",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 1 · Etikk",
|
||||||
|
"front": "Normativ vs. deskriptiv etikk?",
|
||||||
|
"back": "Normativ = hva man <em>bør</em> gjøre (gir veiledning). Deskriptiv = hva folk <em>faktisk</em> mener (beskriver, dømmer ikke)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-003",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 1 · Etikk",
|
||||||
|
"front": "Etisk dilemma vs. moralsk dilemma?",
|
||||||
|
"back": "Etisk dilemma = konflikt mellom <strong>prinsipper/teorier</strong>. Moralsk dilemma = konflikt om hva man <strong>faktisk burde gjøre</strong> her og nå."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-004",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 1 · Etikk",
|
||||||
|
"front": "Ekte vs. falskt dilemma?",
|
||||||
|
"back": "Ekte = begge valg like gode/dårlige, ingen åpenbar fasit (poenget er <strong>god argumentasjon</strong>). Falskt = det er klart hva som er riktig, men fristende å velge noe annet av egeninteresse."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-005",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 1 · Etikk",
|
||||||
|
"front": "De 6 etiske prinsippene — med huskeregel?",
|
||||||
|
"back": "<strong>«La Alle Velge Ikke-skadelig, Rettferdig og Forsiktig»</strong>: Likhet, Autonomi, Velgjørenhet, Ikke-skade, Rettferdighet, Føre-var."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-006",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 1 · Etikk",
|
||||||
|
"front": "Likhet vs. rettferdighet?",
|
||||||
|
"back": "Likhet = <strong>samme</strong> behandling. Rettferdighet = <strong>rimelig</strong> behandling (ulike behov → ulik behandling). Eks: utvidet eksamenstid ved dysleksi er rettferdig, men ikke likt — og helt riktig."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-007",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 1 · Etikk",
|
||||||
|
"front": "Ikke-skade vs. føre-var?",
|
||||||
|
"back": "Ikke-skade = <strong>vi vet det er farlig</strong> (kjent risiko, f.eks. stopp et bevist diskriminerende KI-system). Føre-var = <strong>vi vet ikke nok</strong> (usikker, men potensielt alvorlig risiko → test grundig før lansering)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-008",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 2 · Etikk",
|
||||||
|
"front": "De tre etiske teoriene + opphav — huskeregel?",
|
||||||
|
"back": "<strong>De 3 R-ene:</strong> Resultat = <strong>Mill</strong> (konsekvens/utilitarisme), Regel = <strong>Kant</strong> (pliktetikk), Rollemodell = <strong>Aristoteles</strong> (dydsetikk)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-009",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 2 · Etikk",
|
||||||
|
"front": "Kants kategoriske imperativ — de to formuleringene?",
|
||||||
|
"back": "1) <strong>Universaliserbarhet:</strong> handle bare etter en maksime du kan ville skal bli allmenn lov («ville det vært greit om alle gjorde dette?»). 2) <strong>Humanitet:</strong> behandle mennesker alltid som mål, aldri bare som middel."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-010",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 2 · Etikk",
|
||||||
|
"front": "Konsekvensetikk vs. ikke-konsekvensetikk — vanligste felle?",
|
||||||
|
"back": "At <strong>konsekvensene avgjør</strong> moralsk riktighet er kjernen i utilitarisme (Mill) og <strong>feil for Kant</strong> — hos Kant ligger verdien i motivet/viljen, ikke utfallet."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-011",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 2 · Etikk",
|
||||||
|
"front": "Hva er dydsetikkens særtrekk (Aristoteles)?",
|
||||||
|
"back": "Karakter framfor regler/utfall. Krever <strong>praktisk klokskap (phronesis)</strong> og situasjonsforståelse — kan ikke reduseres til faste regler. Mål: <strong>eudaimonia</strong> (det gode liv)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-012",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 2 · Etikk",
|
||||||
|
"front": "Kvalnes' Navigasjonshjul — de seks perspektivene?",
|
||||||
|
"back": "<strong>JIMØØE:</strong> Juss (lovlig?), Identitet (verdiene våre?), Moral (riktig?), Omdømme (troverdig?), Økonomi (lønner det seg?), Etikk (lar det seg begrunne?). Bruk alle seks på casen."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-013",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 3 · Bærekraft",
|
||||||
|
"front": "Brundtland-definisjonen (1987) — ordrett?",
|
||||||
|
"back": "«En utvikling som imøtekommer dagens behov uten å ødelegge mulighetene for at kommende generasjoner skal få dekket sine behov.»"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-014",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 3 · Bærekraft",
|
||||||
|
"front": "Triple Bottom Line (Elkington)?",
|
||||||
|
"back": "<strong>3 P-er:</strong> People · Planet · Profit. Bærekraft er balansen i snittet. SDG-«kaken»: økonomi ligger inni samfunn, som ligger inni biosfæren — ikke tre likestilte søyler."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-015",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 3 · Bærekraft",
|
||||||
|
"front": "Svak vs. sterk bærekraft?",
|
||||||
|
"back": "Svak = naturkapital kan <strong>erstattes</strong> av annen kapital. Sterk = naturkapital er <strong>kritisk og uerstattelig</strong>."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-016",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 3 · Bærekraft",
|
||||||
|
"front": "Planetens tålegrenser — antall og status?",
|
||||||
|
"back": "<strong>9 grenser</strong> (Stockholm Resilience Centre, fra 2009) for et trygt handlingsrom. Per 2023/25 er <strong>6–7 av 9 overskredet</strong> (bl.a. klima, biologisk mangfold, nitrogen/fosfor)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-017",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 3 · Bærekraft",
|
||||||
|
"front": "Smultringmodellen (Raworth 2017)?",
|
||||||
|
"back": "Indre ring = <strong>sosialt fundament</strong> (under = underforbruk). Ytre ring = <strong>økologisk tak</strong> = tålegrensene (over = overforbruk). Mellom: «et trygt og rettferdig rom for menneskeheten»."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-018",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 3 · Bærekraft",
|
||||||
|
"front": "Bærekraft vs. sirkulær økonomi — felle?",
|
||||||
|
"back": "<strong>Ikke det samme.</strong> Bærekraft = det brede målet (People/Planet/Profit). Sirkulær økonomi = ett <em>verktøy</em> for miljøpilaren. Sirkulær ≠ automatisk bærekraftig (kan være sosialt urettferdig)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-019",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 3 · Bærekraft",
|
||||||
|
"front": "Degrowth: fire pilarer + Hickels poeng?",
|
||||||
|
"back": "Pilarer: <strong>Ressursbevissthet, Rettferdighet, Lokalisering, Livskvalitet</strong>. Hickel: grønn vekst gir bare <strong>relativ</strong> frikobling (utslipp øker saktere enn BNP), mens klimamål krever <strong>absolutt</strong> (utslipp går ned mens BNP vokser)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-020",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 4 · Samfunnsansvar",
|
||||||
|
"front": "CSR vs. CSV?",
|
||||||
|
"back": "CSR = ansvar utover loven, ofte «ved siden av» kjernevirksomheten (filantropi, eksternt press). CSV (Porter & Kramer 2006) = skap <strong>felles verdi</strong> — tjen penger <em>ved å</em> løse samfunnsproblemer, integrert i strategien."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-021",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 4 · Samfunnsansvar",
|
||||||
|
"front": "Carrolls pyramide (1991) — nedenfra og opp?",
|
||||||
|
"back": "<strong>Tjen → Følg → Gjør rett → Gi tilbake:</strong> Økonomisk (vær lønnsom, grunnlaget) → Juridisk (adlyd loven) → Etisk (gjør det rette) → Filantropisk (god bedriftsborger)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-022",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 4 · Samfunnsansvar",
|
||||||
|
"front": "Den klassiske CSR-debatten — fire navn?",
|
||||||
|
"back": "<strong>Bowen (1953)</strong> CSR-far, moralsk ansvar. <strong>Friedman (1970)</strong> kun aksjonærverdi. <strong>Freeman (1984)</strong> stakeholder-teori. <strong>Bakan (2004)</strong> «institusjonalisert psykopati» → krever regulering."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-023",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 4 · Samfunnsansvar",
|
||||||
|
"front": "Mitchells modell (1997) — attributter og toppkategori?",
|
||||||
|
"back": "<strong>MLH:</strong> Makt, Legitimitet, Hastverk → 7 typer. <strong>Avgjørende</strong> = alle tre (høyest prioritet). Miljøaktivist har ofte legitimitet+hastverk uten makt → <em>avhengig</em>, til den allierer seg og blir avgjørende."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-024",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 4 · Samfunnsansvar",
|
||||||
|
"front": "Institusjon vs. virksomhet + isomorfisme + Scotts søyler?",
|
||||||
|
"back": "Institusjon = de usynlige reglene/normene; virksomhet = aktøren som tilpasser seg for <strong>legitimitet</strong>. <strong>Isomorfisme</strong> = organisasjoner blir like pga. press. Scotts søyler: regulativ (lover), normativ (verdier), kulturell-kognitiv («slik gjør vi det her»)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-025",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 4 · Samfunnsansvar",
|
||||||
|
"front": "Eksternaliteter — typer og kobling til CSR?",
|
||||||
|
"back": "Kostnad/fordel som rammer tredjepart uten å fanges av markedsprisen. Negativ = forurensning; positiv = utdanning/vaksinasjon. <strong>Samfunnsansvarlig drift = ta ansvar for de negative = positiv nettoeffekt.</strong>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-026",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 4 · Samfunnsansvar",
|
||||||
|
"front": "Sosial pilar: intern vs. ekstern (+ norsk poeng)?",
|
||||||
|
"back": "Intern: Obligatorisk (lov) → Avtalt (tariff) → <strong>Frivillig (= ekte CSR)</strong>. Ekstern: filantropi, sponsing, Cause Related Marketing. Norsk poeng: mye «ansattgoder» er <em>lovpålagt</em> i Norge → da ikke CSR, men plikt."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-027",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 5 · Verktøy",
|
||||||
|
"front": "Obligatorisk vs. frivillig verktøykasse + ISO-felle?",
|
||||||
|
"back": "Obligatorisk: CSRD, Åpenhetsloven, Regnskapsloven §3-3c, Grunnloven §112. Frivillig: ISO, GRI, Code of Conduct, miljømerker. <strong>Felle: ISO 26000 kan IKKE sertifiseres</strong> (kun veiledende); ISO 14001 og 9001 kan."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-028",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 5 · Verktøy",
|
||||||
|
"front": "CSRD + dobbel vesentlighet?",
|
||||||
|
"back": "CSRD = lovpålagt ESG-rapportering (innfases 2024→2026). <strong>Dobbel vesentlighet = «inn og ut»:</strong> UT = vår påvirkning på klima/samfunn (impact), INN = bærekraftens påvirkning på vår økonomi (financial). Vesentlig i minst ett = inkluderes."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-029",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 5 · Verktøy",
|
||||||
|
"front": "De fem implementeringsstegene?",
|
||||||
|
"back": "<strong>PIRVO:</strong> Planlegging → Interessentdialog → Rapportering → Verifikasjon → Oppfølging. Skill «strategi <em>for</em> bærekraft» (sidespor) fra «bærekraft <em>i</em> strategien» (modent = proaktiv = CSV)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ft-030",
|
||||||
|
"category": "fasttrack",
|
||||||
|
"subcategory": "Modul 5 · Verktøy",
|
||||||
|
"front": "Case-oppskriften (oppgave 4) — fem trinn?",
|
||||||
|
"back": "1) Identifiser utfordringer + interessenter. 2) Velg teori(er), navngi opphav + årstall. 3) Anvend konkret (Mitchell? Carroll-nivå? eksternaliteter?). 4) Drøft alternativer (Friedman vs. Freeman, Navigasjonshjulet). 5) <strong>Konkluder med standpunkt</strong> — og begrunn."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -33,6 +33,10 @@
|
|||||||
<span class="sidebar__link-num">00</span>
|
<span class="sidebar__link-num">00</span>
|
||||||
<span>Oversikt</span>
|
<span>Oversikt</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="#/fast-track" data-route="fasttrack" class="sidebar__link sidebar__link--fasttrack">
|
||||||
|
<span class="sidebar__link-num">»</span>
|
||||||
|
<span>Fast-track</span>
|
||||||
|
</a>
|
||||||
<a href="#/tldr" data-route="tldr" class="sidebar__link sidebar__link--tldr">
|
<a href="#/tldr" data-route="tldr" class="sidebar__link sidebar__link--tldr">
|
||||||
<span class="sidebar__link-num">!</span>
|
<span class="sidebar__link-num">!</span>
|
||||||
<span>tl;dr — i farta</span>
|
<span>tl;dr — i farta</span>
|
||||||
@@ -221,6 +225,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="ft-promo reveal">
|
||||||
|
<a href="#/fast-track" class="ft-promo__card" data-route="fasttrack">
|
||||||
|
<div class="ft-promo__icon">»</div>
|
||||||
|
<div class="ft-promo__body">
|
||||||
|
<div class="ft-promo__label">Fast-track</div>
|
||||||
|
<div class="ft-promo__title">Mye <em>repetisjon</em> mellom ukene? Hopp over den.</div>
|
||||||
|
<div class="ft-promo__desc">Hele pensum kondensert til fem moduler — hvert begrep lært én gang, med huskeregler, eksempler og eksamensfeller. Følg fremdriften din underveis.</div>
|
||||||
|
</div>
|
||||||
|
<div class="ft-promo__arrow">→</div>
|
||||||
|
</a>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="tldr-promo reveal">
|
<section class="tldr-promo reveal">
|
||||||
<a href="#/tldr" class="tldr-promo__card" data-route="tldr">
|
<a href="#/tldr" class="tldr-promo__card" data-route="tldr">
|
||||||
<div class="tldr-promo__icon">!</div>
|
<div class="tldr-promo__icon">!</div>
|
||||||
@@ -346,6 +362,49 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template id="t-fasttrack-home">
|
||||||
|
<div class="page page--narrow">
|
||||||
|
<header class="ft-hero reveal">
|
||||||
|
<div class="ft-hero__badge">Fast-track</div>
|
||||||
|
<h1 class="ft-hero__title">Hele pensum,<br><em>uten gjentakelsen</em></h1>
|
||||||
|
<div class="ft-hero__sub">Faget gjentar seg på tvers av 12 uker. Her lærer du hvert begrep <strong>én gang</strong> — kondensert til fem moduler etter eksamensstrukturen, med huskeregler, eksempler og fellene som trekker ned.</div>
|
||||||
|
<div class="ft-progress reveal">
|
||||||
|
<div class="ft-progress__head">
|
||||||
|
<span class="ft-progress__label">Din fremdrift</span>
|
||||||
|
<span class="ft-progress__count" id="ftProgressCount">0 / 5 moduler</span>
|
||||||
|
</div>
|
||||||
|
<div class="ft-progress__track"><div class="ft-progress__bar" id="ftProgressBar"></div></div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div class="ft-grid" id="ftGrid"></div>
|
||||||
|
|
||||||
|
<div class="ft-test reveal">
|
||||||
|
<div class="ft-test__body">
|
||||||
|
<div class="ft-test__label">Når du har lest</div>
|
||||||
|
<div class="ft-test__title">Test deg på <em>30 Fast-track-kort</em></div>
|
||||||
|
<div class="ft-test__desc">Konsise flashcards som tester nøyaktig huskereglene, skillene og eksamensfellene fra modulene.</div>
|
||||||
|
</div>
|
||||||
|
<a href="#/flashcards/fasttrack" class="ft-test__cta" data-route="flashcards">Start flashcards →</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="t-fasttrack-module">
|
||||||
|
<div class="page page--narrow">
|
||||||
|
<header class="lesson-header reveal">
|
||||||
|
<div class="lesson-header__num" id="ftModNum">Fast-track</div>
|
||||||
|
<h1 class="lesson-header__title" id="ftModTitle">—</h1>
|
||||||
|
<div class="lesson-header__meta">
|
||||||
|
<button class="ft-done-btn" id="ftDoneBtn">Marker som lest</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<article class="lesson tldr-body ft-body" id="ftModBody">
|
||||||
|
<div class="is-loading" style="height: 400px;"></div>
|
||||||
|
</article>
|
||||||
|
<nav class="lesson-pager" id="ftModPager"></nav>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template id="t-tldr">
|
<template id="t-tldr">
|
||||||
<div class="page page--narrow tldr-page">
|
<div class="page page--narrow tldr-page">
|
||||||
<header class="tldr-hero reveal">
|
<header class="tldr-hero reveal">
|
||||||
|
|||||||
@@ -11,8 +11,11 @@ function parseRoute() {
|
|||||||
const parts = hash.split('/').filter(Boolean);
|
const parts = hash.split('/').filter(Boolean);
|
||||||
if (parts[0] === 'uke' && parts[1]) return { name: 'uke', weekId: parseInt(parts[1], 10) };
|
if (parts[0] === 'uke' && parts[1]) return { name: 'uke', weekId: parseInt(parts[1], 10) };
|
||||||
if (parts[0] === 'tema' && parts[1]) return { name: 'tema', temaId: parts[1] };
|
if (parts[0] === 'tema' && parts[1]) return { name: 'tema', temaId: parts[1] };
|
||||||
|
if (parts[0] === 'fast-track') {
|
||||||
|
return parts[1] ? { name: 'fasttrack-module', moduleId: parseInt(parts[1], 10) } : { name: 'fasttrack' };
|
||||||
|
}
|
||||||
if (parts[0] === 'tldr') return { name: 'tldr' };
|
if (parts[0] === 'tldr') return { name: 'tldr' };
|
||||||
if (parts[0] === 'flashcards') return { name: 'flashcards' };
|
if (parts[0] === 'flashcards') return { name: 'flashcards', filter: parts[1] || null };
|
||||||
if (parts[0] === 'quiz') return { name: 'quiz' };
|
if (parts[0] === 'quiz') return { name: 'quiz' };
|
||||||
if (parts[0] === 'eksamen') return { name: 'eksamen' };
|
if (parts[0] === 'eksamen') return { name: 'eksamen' };
|
||||||
return { name: 'home' };
|
return { name: 'home' };
|
||||||
@@ -39,6 +42,15 @@ async function route() {
|
|||||||
const t = SMF.getTheme(r.temaId);
|
const t = SMF.getTheme(r.temaId);
|
||||||
crumb = t ? t.label : 'Tema';
|
crumb = t ? t.label : 'Tema';
|
||||||
break;
|
break;
|
||||||
|
case 'fasttrack':
|
||||||
|
content = await SMF.renderFastTrackHome();
|
||||||
|
crumb = 'Fast-track';
|
||||||
|
break;
|
||||||
|
case 'fasttrack-module':
|
||||||
|
content = await SMF.renderFastTrackModule(r.moduleId);
|
||||||
|
const m = SMF.getFastTrack(r.moduleId);
|
||||||
|
crumb = m ? `Fast-track · ${m.title}` : 'Fast-track';
|
||||||
|
break;
|
||||||
case 'tldr':
|
case 'tldr':
|
||||||
content = await SMF.renderTldr();
|
content = await SMF.renderTldr();
|
||||||
crumb = 'tl;dr · i farta';
|
crumb = 'tl;dr · i farta';
|
||||||
@@ -61,7 +73,7 @@ async function route() {
|
|||||||
crumbCurrent.textContent = crumb;
|
crumbCurrent.textContent = crumb;
|
||||||
|
|
||||||
// After DOM is in place, init relevant mode
|
// After DOM is in place, init relevant mode
|
||||||
if (r.name === 'flashcards') await SMF.fcInit();
|
if (r.name === 'flashcards') await SMF.fcInit(r.filter);
|
||||||
else if (r.name === 'quiz') await SMF.quizInit();
|
else if (r.name === 'quiz') await SMF.quizInit();
|
||||||
else if (r.name === 'eksamen') await SMF.examInit();
|
else if (r.name === 'eksamen') await SMF.examInit();
|
||||||
|
|
||||||
@@ -78,6 +90,8 @@ function updateActiveLinks(r) {
|
|||||||
document.querySelector('.sidebar__link[data-route="home"]')?.classList.add('sidebar__link--active');
|
document.querySelector('.sidebar__link[data-route="home"]')?.classList.add('sidebar__link--active');
|
||||||
} else if (r.name === 'tldr') {
|
} else if (r.name === 'tldr') {
|
||||||
document.querySelector('.sidebar__link[data-route="tldr"]')?.classList.add('sidebar__link--active');
|
document.querySelector('.sidebar__link[data-route="tldr"]')?.classList.add('sidebar__link--active');
|
||||||
|
} else if (r.name === 'fasttrack' || r.name === 'fasttrack-module') {
|
||||||
|
document.querySelector('.sidebar__link[data-route="fasttrack"]')?.classList.add('sidebar__link--active');
|
||||||
} else if (r.name === 'flashcards') {
|
} else if (r.name === 'flashcards') {
|
||||||
document.querySelector('.sidebar__link[data-route="flashcards"]')?.classList.add('sidebar__link--active');
|
document.querySelector('.sidebar__link[data-route="flashcards"]')?.classList.add('sidebar__link--active');
|
||||||
} else if (r.name === 'quiz') {
|
} else if (r.name === 'quiz') {
|
||||||
|
|||||||
@@ -122,6 +122,15 @@ const THEMES = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fast-track — kondensert læringsspor, gjentakelsesfritt, etter eksamensstruktur
|
||||||
|
const FASTTRACK = [
|
||||||
|
{ id: 1, theme: 'etikk', tag: 'Oppgave I', title: 'Etikk — grunnmuren', mins: 8, desc: 'Moral vs. etikk vs. jus, dilemma-typene, og de seks prinsippene som er verktøykassen.' },
|
||||||
|
{ id: 2, theme: 'etikk', tag: 'Oppgave I', title: 'Etikk — teorier & verktøy', mins: 9, desc: 'De tre teoriene (Mill · Kant · Aristoteles), Kants imperativ og Kvalnes-hjulet.' },
|
||||||
|
{ id: 3, theme: 'baerekraft', tag: 'Oppgave II', title: 'Bærekraft', mins: 10, desc: 'Brundtland, Triple Bottom Line, tålegrenser, smultring, sirkulær økonomi og degrowth.' },
|
||||||
|
{ id: 4, theme: 'samfunn', tag: 'Oppgave III', title: 'Samfunnsansvar', mins: 12, desc: 'CSR vs. CSV, Carrolls pyramide, Friedman↔Freeman, Mitchell, eksternaliteter, sosial pilar.' },
|
||||||
|
{ id: 5, theme: 'verktoy', tag: 'Oppgave IV · Case', title: 'Verktøy, implementering & case', mins: 10, desc: 'Standarder, CSRD & dobbel vesentlighet, de fem stegene + ferdig case-oppskrift.' }
|
||||||
|
];
|
||||||
|
|
||||||
// Mapping from theme to color name
|
// Mapping from theme to color name
|
||||||
const THEME_COLORS = {
|
const THEME_COLORS = {
|
||||||
etikk: { color: '#D89AA2', soft: '#4A2027', bg: '#2A1A1D' },
|
etikk: { color: '#D89AA2', soft: '#4A2027', bg: '#2A1A1D' },
|
||||||
@@ -151,9 +160,15 @@ function daysToExam() {
|
|||||||
return { days, hours, label: days === 0 ? `${hours}t` : days === 1 ? '1 dag' : `${days} dager` };
|
return { days, hours, label: days === 0 ? `${hours}t` : days === 1 ? '1 dag' : `${days} dager` };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFastTrack(id) {
|
||||||
|
return FASTTRACK.find(m => m.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
window.SMF = window.SMF || {};
|
window.SMF = window.SMF || {};
|
||||||
SMF.COURSE = COURSE;
|
SMF.COURSE = COURSE;
|
||||||
SMF.WEEKS = WEEKS;
|
SMF.WEEKS = WEEKS;
|
||||||
|
SMF.FASTTRACK = FASTTRACK;
|
||||||
|
SMF.getFastTrack = getFastTrack;
|
||||||
SMF.THEMES = THEMES;
|
SMF.THEMES = THEMES;
|
||||||
SMF.THEME_COLORS = THEME_COLORS;
|
SMF.THEME_COLORS = THEME_COLORS;
|
||||||
SMF.themeOf = themeOf;
|
SMF.themeOf = themeOf;
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ function fcRender() {
|
|||||||
|
|
||||||
function categoryLabel(cat) {
|
function categoryLabel(cat) {
|
||||||
return {
|
return {
|
||||||
|
fasttrack: 'Fast-track',
|
||||||
etikk: 'Etikk',
|
etikk: 'Etikk',
|
||||||
baerekraft: 'Bærekraft',
|
baerekraft: 'Bærekraft',
|
||||||
samfunn: 'Samfunnsansvar',
|
samfunn: 'Samfunnsansvar',
|
||||||
@@ -100,6 +101,7 @@ function fcRenderFilters() {
|
|||||||
if (!container) return;
|
if (!container) return;
|
||||||
const filters = [
|
const filters = [
|
||||||
{ id: 'all', label: 'Alle' },
|
{ id: 'all', label: 'Alle' },
|
||||||
|
{ id: 'fasttrack', label: '» Fast-track' },
|
||||||
{ id: 'new', label: 'Nye' },
|
{ id: 'new', label: 'Nye' },
|
||||||
{ id: 'hard', label: 'Glemt' },
|
{ id: 'hard', label: 'Glemt' },
|
||||||
{ id: 'etikk', label: 'Etikk' },
|
{ id: 'etikk', label: 'Etikk' },
|
||||||
@@ -144,8 +146,13 @@ function fcMark(level) {
|
|||||||
fcNext();
|
fcNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fcInit() {
|
async function fcInit(initialFilter) {
|
||||||
await fcLoad();
|
await fcLoad();
|
||||||
|
// Dyplenke, f.eks. #/flashcards/fasttrack — sett startfilter hvis gyldig
|
||||||
|
if (initialFilter) {
|
||||||
|
const valid = ['all', 'fasttrack', 'new', 'hard', 'etikk', 'baerekraft', 'samfunn', 'verktoy', 'case'];
|
||||||
|
if (valid.includes(initialFilter)) fcState.filter = initialFilter;
|
||||||
|
}
|
||||||
fcState.cards = fcFilterCards(fcState.filter);
|
fcState.cards = fcFilterCards(fcState.filter);
|
||||||
fcShuffle(fcState.cards);
|
fcShuffle(fcState.cards);
|
||||||
fcState.index = 0;
|
fcState.index = 0;
|
||||||
@@ -177,7 +184,7 @@ async function fcInit() {
|
|||||||
|
|
||||||
// Keyboard
|
// Keyboard
|
||||||
const handler = (e) => {
|
const handler = (e) => {
|
||||||
if (location.hash !== '#/flashcards') {
|
if (!location.hash.startsWith('#/flashcards')) {
|
||||||
document.removeEventListener('keydown', handler);
|
document.removeEventListener('keydown', handler);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
145
app/js/render.js
145
app/js/render.js
@@ -238,6 +238,149 @@ async function renderTema(temaId) {
|
|||||||
return tpl;
|
return tpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============= Fast-track =============
|
||||||
|
const FT_PROGRESS_KEY = 'smf-fasttrack-done';
|
||||||
|
|
||||||
|
function ftGetDone() {
|
||||||
|
try { return new Set(JSON.parse(localStorage.getItem(FT_PROGRESS_KEY) || '[]')); }
|
||||||
|
catch { return new Set(); }
|
||||||
|
}
|
||||||
|
function ftSetDone(set) {
|
||||||
|
localStorage.setItem(FT_PROGRESS_KEY, JSON.stringify([...set]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract a single module from fast-track.md by its <!--MODULE:n--> sentinel
|
||||||
|
function extractFastTrackModule(markdown, moduleId) {
|
||||||
|
const startRe = new RegExp(`<!--MODULE:${moduleId}-->`);
|
||||||
|
const lines = markdown.split('\n');
|
||||||
|
let start = lines.findIndex(l => startRe.test(l));
|
||||||
|
if (start === -1) return null;
|
||||||
|
let end = lines.length;
|
||||||
|
for (let i = start + 1; i < lines.length; i++) {
|
||||||
|
if (/<!--MODULE:\d+-->/.test(lines[i])) { end = i; break; }
|
||||||
|
}
|
||||||
|
let section = lines.slice(start + 1, end).join('\n').trim();
|
||||||
|
// Strip the leading "## ..." heading — it's shown in the module header
|
||||||
|
section = section.replace(/^##\s+[^\n]+\n+/, '');
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderFastTrackHome() {
|
||||||
|
const tpl = document.getElementById('t-fasttrack-home').content.cloneNode(true);
|
||||||
|
const grid = tpl.getElementById('ftGrid');
|
||||||
|
const done = ftGetDone();
|
||||||
|
const total = SMF.FASTTRACK.length;
|
||||||
|
const completed = SMF.FASTTRACK.filter(m => done.has(m.id)).length;
|
||||||
|
|
||||||
|
// Progress bar
|
||||||
|
const bar = tpl.getElementById('ftProgressBar');
|
||||||
|
if (bar) bar.style.width = `${Math.round((completed / total) * 100)}%`;
|
||||||
|
const count = tpl.getElementById('ftProgressCount');
|
||||||
|
if (count) count.textContent = `${completed} / ${total} moduler`;
|
||||||
|
|
||||||
|
SMF.FASTTRACK.forEach(m => {
|
||||||
|
const colors = SMF.THEME_COLORS[m.theme] || SMF.THEME_COLORS.all;
|
||||||
|
const isDone = done.has(m.id);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = `#/fast-track/${m.id}`;
|
||||||
|
a.className = 'ft-card reveal' + (isDone ? ' ft-card--done' : '');
|
||||||
|
a.style.setProperty('--ft-color', colors.color);
|
||||||
|
a.style.setProperty('--ft-bg', colors.bg);
|
||||||
|
a.innerHTML = `
|
||||||
|
<div class="ft-card__top">
|
||||||
|
<span class="ft-card__num">${String(m.id).padStart(2, '0')}</span>
|
||||||
|
<span class="ft-card__check" aria-hidden="true">✓</span>
|
||||||
|
</div>
|
||||||
|
<div class="ft-card__eyebrow">${m.tag}</div>
|
||||||
|
<h3 class="ft-card__title">${m.title}</h3>
|
||||||
|
<p class="ft-card__desc">${m.desc}</p>
|
||||||
|
<div class="ft-card__foot">
|
||||||
|
<span class="ft-card__mins">~${m.mins} min</span>
|
||||||
|
<span class="ft-card__arrow">${isDone ? 'Repetér' : 'Start'} →</span>
|
||||||
|
</div>`;
|
||||||
|
grid.appendChild(a);
|
||||||
|
});
|
||||||
|
|
||||||
|
return tpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderFastTrackModule(moduleId) {
|
||||||
|
const tpl = document.getElementById('t-fasttrack-module').content.cloneNode(true);
|
||||||
|
const module = SMF.getFastTrack(moduleId);
|
||||||
|
if (!module) {
|
||||||
|
tpl.getElementById('ftModNum').textContent = 'Ikke funnet';
|
||||||
|
tpl.getElementById('ftModTitle').textContent = 'Ukjent modul';
|
||||||
|
return tpl;
|
||||||
|
}
|
||||||
|
const colors = SMF.THEME_COLORS[module.theme] || SMF.THEME_COLORS.all;
|
||||||
|
|
||||||
|
const num = tpl.getElementById('ftModNum');
|
||||||
|
num.textContent = `Fast-track · Modul ${String(moduleId).padStart(2, '0')} · ${module.tag}`;
|
||||||
|
num.style.color = colors.color;
|
||||||
|
tpl.getElementById('ftModTitle').innerHTML = formatTitleWithEm(module.title);
|
||||||
|
|
||||||
|
const body = tpl.getElementById('ftModBody');
|
||||||
|
try {
|
||||||
|
const md = await loadNote('fast-track.md');
|
||||||
|
const section = extractFastTrackModule(md, moduleId);
|
||||||
|
body.innerHTML = section
|
||||||
|
? renderMarkdown(section)
|
||||||
|
: '<p>Fant ikke modulinnholdet.</p>';
|
||||||
|
} catch (e) {
|
||||||
|
body.innerHTML = `<p>Klarte ikke laste modulen: ${e.message}</p>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Mark as read" toggle
|
||||||
|
const doneBtn = tpl.getElementById('ftDoneBtn');
|
||||||
|
function syncDoneBtn() {
|
||||||
|
const done = ftGetDone();
|
||||||
|
const isDone = done.has(moduleId);
|
||||||
|
doneBtn.classList.toggle('ft-done-btn--active', isDone);
|
||||||
|
doneBtn.textContent = isDone ? '✓ Markert som lest' : 'Marker som lest';
|
||||||
|
}
|
||||||
|
doneBtn.addEventListener('click', () => {
|
||||||
|
const done = ftGetDone();
|
||||||
|
if (done.has(moduleId)) done.delete(moduleId); else done.add(moduleId);
|
||||||
|
ftSetDone(done);
|
||||||
|
syncDoneBtn();
|
||||||
|
});
|
||||||
|
syncDoneBtn();
|
||||||
|
|
||||||
|
// Pager
|
||||||
|
const idx = SMF.FASTTRACK.findIndex(m => m.id === moduleId);
|
||||||
|
const prev = idx > 0 ? SMF.FASTTRACK[idx - 1] : null;
|
||||||
|
const next = idx < SMF.FASTTRACK.length - 1 ? SMF.FASTTRACK[idx + 1] : null;
|
||||||
|
const pager = tpl.getElementById('ftModPager');
|
||||||
|
if (prev) {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = `#/fast-track/${prev.id}`;
|
||||||
|
a.className = 'pager-link pager-link--prev';
|
||||||
|
a.innerHTML = `<div class="pager-link__dir">← Modul ${prev.id}</div><div class="pager-link__title">${prev.title}</div>`;
|
||||||
|
pager.appendChild(a);
|
||||||
|
} else {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = '#/fast-track';
|
||||||
|
a.className = 'pager-link pager-link--prev';
|
||||||
|
a.innerHTML = `<div class="pager-link__dir">← Oversikt</div><div class="pager-link__title">Alle moduler</div>`;
|
||||||
|
pager.appendChild(a);
|
||||||
|
}
|
||||||
|
if (next) {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = `#/fast-track/${next.id}`;
|
||||||
|
a.className = 'pager-link pager-link--next';
|
||||||
|
a.innerHTML = `<div class="pager-link__dir">Modul ${next.id} →</div><div class="pager-link__title">${next.title}</div>`;
|
||||||
|
pager.appendChild(a);
|
||||||
|
} else {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = '#/tldr';
|
||||||
|
a.className = 'pager-link pager-link--next';
|
||||||
|
a.innerHTML = `<div class="pager-link__dir">Ferdig! → tl;dr</div><div class="pager-link__title">Siste-minutts-repetisjon</div>`;
|
||||||
|
pager.appendChild(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tpl;
|
||||||
|
}
|
||||||
|
|
||||||
// ============= TL;DR view =============
|
// ============= TL;DR view =============
|
||||||
async function renderTldr() {
|
async function renderTldr() {
|
||||||
const tpl = document.getElementById('t-tldr').content.cloneNode(true);
|
const tpl = document.getElementById('t-tldr').content.cloneNode(true);
|
||||||
@@ -257,6 +400,8 @@ SMF.renderHome = renderHome;
|
|||||||
SMF.renderLesson = renderLesson;
|
SMF.renderLesson = renderLesson;
|
||||||
SMF.renderTema = renderTema;
|
SMF.renderTema = renderTema;
|
||||||
SMF.renderTldr = renderTldr;
|
SMF.renderTldr = renderTldr;
|
||||||
|
SMF.renderFastTrackHome = renderFastTrackHome;
|
||||||
|
SMF.renderFastTrackModule = renderFastTrackModule;
|
||||||
SMF.loadNote = loadNote;
|
SMF.loadNote = loadNote;
|
||||||
SMF.renderMarkdown = renderMarkdown;
|
SMF.renderMarkdown = renderMarkdown;
|
||||||
SMF.extractWeekSection = extractWeekSection;
|
SMF.extractWeekSection = extractWeekSection;
|
||||||
|
|||||||
239
notes/fast-track.md
Normal file
239
notes/fast-track.md
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
# Fast-track — hele pensum uten gjentakelse
|
||||||
|
|
||||||
|
Faget gjentar seg selv på tvers av 12 uker: Brundtland dukker opp i uke 2, 7 og 16; Triple Bottom Line i uke 2, 7, 8 og 10; Friedman og Freeman i uke 6, 7 og 8; de seks prinsippene i uke 3 og 5. **Fast-track lærer hvert begrep én gang** — organisert etter de fire eksamensoppgavene, ikke etter uke. Hver modul gir deg kjernen, en huskeregel, et konkret eksempel du kan bruke, og fellene som trekker ned.
|
||||||
|
|
||||||
|
<!--MODULE:1-->
|
||||||
|
|
||||||
|
## Modul 1 · Etikk — grunnmuren
|
||||||
|
|
||||||
|
> **Mål:** Kunne definere etikk presist, skille de nære begrepene, og kjenne de seks prinsippene som er verktøykassen i all etisk vurdering.
|
||||||
|
|
||||||
|
### Etikk vs. moral vs. jus
|
||||||
|
|
||||||
|
Dette skillet kommer nesten alltid som kortsvar. Hold det knivskarpt:
|
||||||
|
|
||||||
|
| Begrep | Hva det er | Læres |
|
||||||
|
|---|---|---|
|
||||||
|
| **Etikk** | Systematisk *refleksjon* over rett og galt — et fag | Gjennom studier |
|
||||||
|
| **Moral** | De *praktiserte* normene og verdiene våre | Gjennom omgang med andre |
|
||||||
|
| **Jus** | Det *formelle* regelverket håndhevet av staten | Vedtas og kodifiseres |
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div><strong>Etikk = teori. Moral = praksis. Jus = paragraf.</strong> Etikk spør «hvorfor er det galt?», moral sier «sånn gjør vi det», jus sier «det står i loven».</div></div>
|
||||||
|
|
||||||
|
To beslektede par du må kunne:
|
||||||
|
|
||||||
|
- **Normativ etikk** = hva man *bør* gjøre (gir veiledning). **Deskriptiv etikk** = hva folk *faktisk* mener (beskriver, dømmer ikke).
|
||||||
|
- **Etisk dilemma** = konflikt mellom *prinsipper/teorier*. **Moralsk dilemma** = konflikt om hva man *faktisk burde gjøre* her og nå.
|
||||||
|
|
||||||
|
### Ekte vs. falskt dilemma
|
||||||
|
|
||||||
|
- **Ekte dilemma:** begge valg er like gode/dårlige — ingen er åpenbart riktig. (Eks: varsle om miljøskade og risikere oppsigelse, eller tie?)
|
||||||
|
- **Falskt dilemma:** det er klart hva som er riktig, men fristende å velge noe annet av egeninteresse. (Eks: jukse på eksamen.)
|
||||||
|
|
||||||
|
<div class="callout callout--felle"><span class="callout__label">Eksamensfelle</span><div>Et <strong>ekte</strong> dilemma har ingen fasit — poenget er <strong>god argumentasjon</strong>, ikke å «velge riktig». Falskt dilemma er egentlig en fristelse, ikke et dilemma.</div></div>
|
||||||
|
|
||||||
|
### De 6 etiske prinsippene
|
||||||
|
|
||||||
|
Medisinsk-etiske prinsipper som også brukes i næringslivet. Lær dem utenat — de er verktøyet i case-drøftingen.
|
||||||
|
|
||||||
|
1. **Likhet** — like tilfeller behandles likt; samme regler for alle.
|
||||||
|
2. **Autonomi** — retten til å bestemme over seg selv.
|
||||||
|
3. **Velgjørenhet** — plikten til aktivt å gjøre godt.
|
||||||
|
4. **Ikke-skade** — ikke påføre skade ved **kjent** risiko.
|
||||||
|
5. **Rettferdighet** — rimelig fordeling; ulike behov kan kreve ulik behandling.
|
||||||
|
6. **Føre-var** — vær forsiktig ved **usikker, men potensielt alvorlig** risiko.
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div><strong>«La Alle Velge Ikke-skadelig, Rettferdig og Forsiktig»</strong> → <strong>L</strong>ikhet, <strong>A</strong>utonomi, <strong>V</strong>elgjørenhet, <strong>I</strong>kke-skade, <strong>R</strong>ettferdighet, <strong>F</strong>øre-var.</div></div>
|
||||||
|
|
||||||
|
To kontraster som testes igjen og igjen:
|
||||||
|
|
||||||
|
- **Likhet vs. rettferdighet:** Likhet = *samme* behandling. Rettferdighet = *rimelig* behandling. Utvidet eksamenstid for en student med dysleksi er rettferdig, men ikke lik behandling — og det er helt riktig.
|
||||||
|
- **Ikke-skade vs. føre-var:** Ikke-skade = *vi vet det er farlig* (et bevist diskriminerende KI-system bør stoppes). Føre-var = *vi vet ikke nok* (et nytt KI-system med ukjente konsekvenser bør testes grundig før lansering).
|
||||||
|
|
||||||
|
<div class="callout callout--eksempel"><span class="callout__label">Bruk dette eksempelet</span><div><strong>KI i rekruttering:</strong> En HR-modell rangerer søkere raskt, men viser bias. Her kolliderer <strong>rettferdighet</strong> (ikke diskriminere) med <strong>autonomi</strong> (kandidatene samtykket til databruk) og <strong>ikke-skade/føre-var</strong>. Ett eksempel som dekker fire prinsipper.</div></div>
|
||||||
|
|
||||||
|
<!--MODULE:2-->
|
||||||
|
|
||||||
|
## Modul 2 · Etikk — de tre teoriene & beslutningsverktøyene
|
||||||
|
|
||||||
|
> **Mål:** Knytte riktig teoretiker til riktig teori, kjenne Kants to formuleringer, og kunne bruke Navigasjonshjulet aktivt på en case.
|
||||||
|
|
||||||
|
### De tre store teoriene
|
||||||
|
|
||||||
|
Hovedaksen er **konsekvensetikk** (ser på utfallet) vs. **ikke-konsekvensetikk** (ser på plikt eller karakter).
|
||||||
|
|
||||||
|
| Teori | Opphav | Hva teller | Hovedspørsmål |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **Konsekvensetikk / utilitarisme** | **Mill** | Konsekvensene for alle | «Hva gir mest lykke for flest?» |
|
||||||
|
| **Pliktetikk (deontologi)** | **Kant** | Plikt og regel, uansett utfall | «Er handlingen riktig i seg selv?» |
|
||||||
|
| **Dydsetikk** | **Aristoteles** | Personens karakter | «Hva ville et godt menneske gjort?» |
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div><strong>De 3 R-ene:</strong> <strong>R</strong>esultat (Mill), <strong>R</strong>egel (Kant), <strong>R</strong>ollemodell (Aristoteles). Knytt alltid navnet til teorien — det er en gratis-feil å bytte dem om.</div></div>
|
||||||
|
|
||||||
|
### Kants kategoriske imperativ — to formuleringer
|
||||||
|
|
||||||
|
1. **Universaliserbarhet:** «Handle bare etter den maksimen du samtidig kan ville skal bli en allmenn lov.» → *Ville det vært greit om alle gjorde dette?*
|
||||||
|
2. **Humanitetsformuleringen:** Behandle mennesker «alltid som et mål, aldri bare som et middel.»
|
||||||
|
|
||||||
|
<div class="callout callout--eksempel"><span class="callout__label">Bruk dette eksempelet</span><div><strong>Villedende markedsføring (Kant):</strong> «Ville det vært greit om alle bedrifter løy i reklamen?» Nei — det ville rasere tilliten markedet hviler på. I tillegg brukes kunden <strong>bare som middel</strong> til salg. Dobbelt fordømt av Kant.</div></div>
|
||||||
|
|
||||||
|
Tre nyanser sensor liker å høre:
|
||||||
|
- **Utilitarismens svakhet:** kan rettferdiggjøre overgrep mot et mindretall hvis det øker totalnytten; lykke er vanskelig å måle.
|
||||||
|
- **Dydsetikkens særtrekk:** krever **praktisk klokskap (phronesis)** og situasjonsforståelse — kan *ikke* reduseres til faste regler. Målet er **eudaimonia** (det gode liv).
|
||||||
|
- **Diskursetikk** (Habermas-inspirert): det rette finnes gjennom åpen, tvangsfri dialog der det beste argumentet vinner.
|
||||||
|
|
||||||
|
### Kvalnes' Navigasjonshjul — verktøyet for oppgave 4
|
||||||
|
|
||||||
|
Spør «Hva gjør du?» fra seks perspektiver før du beslutter:
|
||||||
|
|
||||||
|
| Perspektiv | Spørsmål |
|
||||||
|
|---|---|
|
||||||
|
| **Juss** | Er det lovlig? |
|
||||||
|
| **Identitet** | Er det i samsvar med verdiene våre? |
|
||||||
|
| **Moral** | Er det riktig? |
|
||||||
|
| **Omdømme** | Beholder vi troverdigheten? |
|
||||||
|
| **Økonomi** | Lønner det seg? |
|
||||||
|
| **Etikk** | Lar det seg begrunne? |
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div>Navigasjonshjulet = <strong>JIMØØE</strong> (Juss, Identitet, Moral, Omdømme, Økonomi, Etikk). Bruk det aktivt på casen — gå gjennom alle seks, ikke bare nevn at det finnes.</div></div>
|
||||||
|
|
||||||
|
**Crane & Mattens 5-fasemodell** (alternativt rammeverk): Identifisere problem → Innhente informasjon → Velge mellom alternativer → Gjennomføre → Resultat/læring (sirkulær, sløyfer tilbake).
|
||||||
|
|
||||||
|
<div class="callout callout--felle"><span class="callout__label">Eksamensfelle</span><div>Ikke bland sammen <strong>konsekvensetikk</strong> og Kant: at konsekvensene avgjør moralsk riktighet er <em>kjernen i utilitarisme</em> og <em>feil</em> for Kant. Hos Kant ligger verdien i motivet/viljen.</div></div>
|
||||||
|
|
||||||
|
<!--MODULE:3-->
|
||||||
|
|
||||||
|
## Modul 3 · Bærekraft
|
||||||
|
|
||||||
|
> **Mål:** Definere bærekraft ordrett, kjenne de tre pilarene og modellene (tålegrenser, smultring, sirkulær økonomi), og kunne skille bærekraft fra sirkulær økonomi.
|
||||||
|
|
||||||
|
### Fundamentet
|
||||||
|
|
||||||
|
- **Brundtland (1987)** — lær ordrett: «En utvikling som imøtekommer dagens behov uten å ødelegge mulighetene for at kommende generasjoner skal få dekket sine behov.»
|
||||||
|
- **Triple Bottom Line (Elkington 1994/97):** **People · Planet · Profit** — bærekraft er balansen i snittet av de tre.
|
||||||
|
- **Svak vs. sterk bærekraft:** Svak = naturkapital kan erstattes av annen kapital. Sterk = naturkapital er kritisk og uerstattelig.
|
||||||
|
- **SDG:** 17 mål, 169 delmål, vedtatt 2015, frist 2030.
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div><strong>3 P-er:</strong> People, Planet, Profit. SDG-«kaken»: økonomien ligger <em>inni</em> samfunnet, som ligger <em>inni</em> biosfæren — ikke tre likestilte søyler. Biosfæren bærer alt.</div></div>
|
||||||
|
|
||||||
|
### Tre modeller du må kunne
|
||||||
|
|
||||||
|
- **Planetens tålegrenser** (Stockholm Resilience Centre, fra 2009): 9 grenser for et trygt handlingsrom. **Per 2023/25 er 6–7 av 9 overskredet** (bl.a. klima, biologisk mangfold, nitrogen/fosfor).
|
||||||
|
- **Smultringmodellen (Raworth 2017):** Indre ring = **sosialt fundament** (grunnbehov; under = underforbruk). Ytre ring = **økologisk tak** (tålegrensene; over = overforbruk). Mellom dem: «et trygt og rettferdig rom for menneskeheten».
|
||||||
|
- **Sirkulær økonomi** (Oxford 2022): lukket loop — *Råmaterialer → bærekraftig design → produksjon → distribusjon → bruk/gjenbruk/reparasjon → innsamling → resirkulering*. Reduserer uttak, avfall og utslipp.
|
||||||
|
|
||||||
|
<div class="callout callout--felle"><span class="callout__label">Eksamensfelle</span><div><strong>Bærekraft ≠ sirkulær økonomi.</strong> Bærekraft er det <em>brede målet</em> (People/Planet/Profit). Sirkulær økonomi er ett <em>verktøy</em> for miljø-pilaren. Sirkulær ≠ automatisk bærekraftig (kan være sosialt urettferdig).</div></div>
|
||||||
|
|
||||||
|
**Lineær → resirkulering → sirkulær:** Take-Make-Use-**Waste** (mye avfall) → legger til Recycle (mindre) → Reuse/Repair/Recycle/Return (mål: null avfall). **10R-rammeverket (Kirchherr)** rangerer strategier fra mest sirkulær (R0 Refuse) til minst (R9 Recover/energigjenvinning).
|
||||||
|
|
||||||
|
### Vekst-debatten (uke 16)
|
||||||
|
|
||||||
|
- **Grønn vekst:** fortsett å vokse, men miljøvennlig.
|
||||||
|
- **Motvekst / degrowth:** begrens veksten — uendelig vekst er uforenlig med planetens grenser. Fire pilarer: **Ressursbevissthet, Rettferdighet, Lokalisering, Livskvalitet**.
|
||||||
|
- **Jason Hickel** (*Less is More*): grønn vekst gir i praksis bare **relativ frikobling** (utslipp øker saktere enn BNP), mens klimamålene krever **absolutt frikobling** (utslipp går *ned* mens BNP vokser).
|
||||||
|
|
||||||
|
<div class="callout callout--eksempel"><span class="callout__label">Norske eksempler å nevne</span><div><strong>IKEA Norge</strong> (reparasjon/videresalg = sirkulær), <strong>Tomra</strong> (pantesystem), <strong>Storebrand/Oljefondet</strong> (ESG-screening), <strong>Equinor</strong> (energiomstilling — case-gull). Norge er bare <strong>2,4 % sirkulær</strong> (verden ~8,6 %) — et tall som imponerer.</div></div>
|
||||||
|
|
||||||
|
<!--MODULE:4-->
|
||||||
|
|
||||||
|
## Modul 4 · Samfunnsansvar (CSR)
|
||||||
|
|
||||||
|
> **Mål:** Definere CSR og CSV, kjenne Carrolls pyramide og den klassiske debatten, og kunne kartlegge interessenter med Mitchells modell.
|
||||||
|
|
||||||
|
### Kjernedefinisjoner
|
||||||
|
|
||||||
|
- **CSR:** ansvaret selskaper påtar seg for miljø, samfunn og mennesker — **utover** det lovpålagte.
|
||||||
|
- **CSV (Porter & Kramer 2006):** skap *felles* verdi — bedriften tjener penger *ved å* løse samfunnsproblemer.
|
||||||
|
- **Eksternaliteter:** kostnader/fordeler som rammer en tredjepart uten å fanges av markedsprisen. Negativ = forurensning; positiv = utdanning/vaksinasjon. **Samfunnsansvarlig drift = ta ansvar for de negative eksternalitetene = positiv nettoeffekt** (s. 200).
|
||||||
|
|
||||||
|
<div class="callout callout--felle"><span class="callout__label">CSR vs. CSV — kommer ofte</span><div><strong>CSR</strong> er ofte eksternt drevet og ligger «ved siden av» kjernevirksomheten (filantropi). <strong>CSV</strong> er integrert i strategien og kobler samfunnsnytte direkte til verdiskaping. CSV er «syntesen» som demper Friedman-vs-Freeman-konflikten.</div></div>
|
||||||
|
|
||||||
|
### Carrolls pyramide (1991)
|
||||||
|
|
||||||
|
Fire nivåer nedenfra og opp — det nederste bærer resten:
|
||||||
|
|
||||||
|
1. **Økonomisk** — vær lønnsom (grunnlaget; uten dette ingen bedrift).
|
||||||
|
2. **Juridisk** — adlyd loven.
|
||||||
|
3. **Etisk** — gjør det riktige, også når loven ikke krever det.
|
||||||
|
4. **Filantropisk** — vær en god bedriftsborger (frivillig).
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div>Pyramiden nedenfra: <strong>Tjen → Følg → Gjør rett → Gi tilbake.</strong> (Økonomisk, Juridisk, Etisk, Filantropisk.) Økonomisk er bunnen <em>fordi</em> en bedrift som ikke tjener penger ikke kan eksistere — og dermed ikke oppfylle de andre.</div></div>
|
||||||
|
|
||||||
|
### Den klassiske debatten — fire posisjoner
|
||||||
|
|
||||||
|
- **Bowen (1953):** «CSR-feltets far» — bedrifter har moralsk ansvar utover profitt.
|
||||||
|
- **Friedman (1970):** «The social responsibility of business is to increase its profits» — aksjonærverdi innenfor lovens rammer; markedet, ikke bedriften, løser samfunnsproblemer.
|
||||||
|
- **Freeman (1984):** stakeholder-teori — balanser alle som påvirkes (ansatte, kunder, leverandører, lokalsamfunn, miljø), ikke bare aksjonærene.
|
||||||
|
- **Bakan (2004):** *The Corporation* — bedriften er «institusjonalisert psykopati» som strukturelt jakter profitt; krever demokratisk regulering.
|
||||||
|
|
||||||
|
<div class="callout callout--eksempel"><span class="callout__label">Slik bruker du debatten</span><div>«På den ene siden hevder <strong>Friedman (1970)</strong> at… På den andre siden argumenterer <strong>Freeman (1984)</strong> for… <strong>Porter & Kramer (CSV)</strong> løser spenningen ved at profitt og samfunnsnytte forenes.» Denne trekanten hever et hvilket som helst svar.</div></div>
|
||||||
|
|
||||||
|
### Interessenter & institusjoner
|
||||||
|
|
||||||
|
- **Stakeholder vs. shareholder:** interessent (alle som påvirkes/påvirker) vs. aksjonær (eier).
|
||||||
|
- **Mitchell, Agle & Wood (1997):** tre attributter — **Makt, Legitimitet, Hastverk** → 7 typer. **Avgjørende** = alle tre (høyest prioritet). To av tre: dominerende (makt+legitimitet), avhengig (legitimitet+hastverk), farlig (makt+hastverk). Én: sovende (makt), frivillig (legitimitet), krevende (hastverk).
|
||||||
|
- **Institusjonell teori:** *institusjon* = de usynlige reglene/normene/forventningene; *virksomhet* = den konkrete aktøren som tilpasser seg for å få **legitimitet**. **Isomorfisme** = organisasjoner blir like pga. press. **Scotts tre søyler:** regulativ (lover), normativ (verdier), kulturell-kognitiv («slik gjør vi det her»).
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div>Mitchell = <strong>MLH</strong> (Makt, Legitimitet, Hastverk). En miljøaktivist har ofte legitimitet + hastverk men mangler makt → <strong>avhengig</strong>, til den allierer seg med medier/myndigheter og blir <strong>avgjørende</strong>.</div></div>
|
||||||
|
|
||||||
|
### Sosial pilar (uke 10)
|
||||||
|
|
||||||
|
- **Intern søyle:** Obligatorisk (lov, Arbeidsmiljøloven) → Avtalt (tariff/fagforening) → **Frivillig (= ekte CSR)**.
|
||||||
|
- **Ekstern søyle:** filantropi, sponsing, **Cause Related Marketing** (CRM — donér per kjøp).
|
||||||
|
|
||||||
|
<div class="callout callout--felle"><span class="callout__label">Norsk poeng som imponerer</span><div>Mye som er «frivillige ansattgoder» i USA er <strong>lovpålagt i Norge</strong> (folketrygd, ferie) — da er det <em>ikke</em> CSR, men en plikt. Bare den <strong>frivillige</strong> delen er strengt tatt CSR. Klassisk CRM-eksempel: American Express + Frihetsgudinnen (1983).</div></div>
|
||||||
|
|
||||||
|
<!--MODULE:5-->
|
||||||
|
|
||||||
|
## Modul 5 · Verktøy, implementering & case-oppskrift
|
||||||
|
|
||||||
|
> **Mål:** Kjenne verktøykassen (standarder, lover, CSRD), de fem implementeringsstegene, og ha en ferdig mal for case-oppgaven (oppgave 4).
|
||||||
|
|
||||||
|
### Obligatorisk vs. frivillig verktøykasse
|
||||||
|
|
||||||
|
| Obligatorisk (må) | Frivillig (velger) |
|
||||||
|
|---|---|
|
||||||
|
| CSRD, Åpenhetsloven (2022), Regnskapsloven §3-3c, Grunnloven §112 | ISO-standarder, GRI, Code of Conduct, miljømerker |
|
||||||
|
|
||||||
|
- **ISO-trekanten:** **ISO 26000** = People/samfunnsansvar (*ikke* sertifiserbar, kun veiledende) · **ISO 14001** = Planet/miljø (sertifiserbar) · **ISO 9001** = Profit/kvalitet (sertifiserbar).
|
||||||
|
- **GRI** = mest brukte globale rapporteringsstandard — bærekraftsrapporteringens «felles språk».
|
||||||
|
- **Reaktiv** (defensiv, beskytt omdømme) vs. **proaktiv** (integrert i strategi/DNA — mest moden, gir konkurransefortrinn).
|
||||||
|
|
||||||
|
<div class="callout callout--felle"><span class="callout__label">Eksamensfelle</span><div><strong>ISO 26000 kan ikke sertifiseres</strong> — den er kun veiledende. ISO 14001 og 9001 kan sertifiseres. Dette spørres direkte.</div></div>
|
||||||
|
|
||||||
|
### EU-rammeverket & CSRD
|
||||||
|
|
||||||
|
- **Green Deal:** klimanøytralt Europa innen 2050.
|
||||||
|
- **CSRD** (Corporate Sustainability Reporting Directive): lovpålagt ESG-rapportering — innfases 2024 (store allmenn-interesse) → 2025 (store foretak) → 2026 (børsnoterte SMB).
|
||||||
|
- **Dobbel vesentlighet** = CSRD-kjernen: rapporter både **påvirkning UT** (impact materiality — hvordan vi påvirker omverdenen) og **påvirkning INN** (financial materiality — hvordan bærekraft påvirker vår økonomi).
|
||||||
|
- **ESRS-temaer:** E1–E5 (miljø), S1–S4 (sosial), G1 (styring). **EU-taksonomien** = klassifisering av hva som er «grønt».
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div>Dobbel vesentlighet = <strong>«inn og ut»</strong>. UT = vår effekt på klima/samfunn. INN = klima/reguleringers effekt på vår bunnlinje. Et tema teller hvis det er vesentlig i <em>minst ett</em> av perspektivene.</div></div>
|
||||||
|
|
||||||
|
### De 5 implementeringsstegene (uke 16)
|
||||||
|
|
||||||
|
**Planlegging → Interessentdialog → Rapportering → Verifikasjon → Oppfølging.**
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Huskeregel</span><div><strong>PIRVO.</strong> Verktøyene fra denne modulen plugges rett inn: Rapportering ↔ GRI/CSRD, Verifikasjon ↔ ISO 14001-sertifisering. Skill «<em>strategi for</em> bærekraft» (sidespor) fra «<em>bærekraft i</em> strategien» (modent, = proaktiv = CSV-tankegang).</div></div>
|
||||||
|
|
||||||
|
### Case-oppskriften (oppgave 4 — 25 %)
|
||||||
|
|
||||||
|
En bombesikker struktur som funker på enhver case:
|
||||||
|
|
||||||
|
1. **Identifiser** de etiske/bærekrafts-utfordringene og **interessentene** i casen.
|
||||||
|
2. **Velg teori(er)** og navngi opphav + årstall (Carroll 1991, Freeman 1984, Mitchell 1997, Porter & Kramer 2006…).
|
||||||
|
3. **Anvend** teorien konkret: Hvem er avgjørende interessent (Mitchell)? Hvilket pyramidenivå krenkes (Carroll)? Hvilke eksternaliteter oppstår?
|
||||||
|
4. **Drøft alternativer:** Hva ville Friedman gjort? Freeman? Hva sier Navigasjonshjulet?
|
||||||
|
5. **Konkluder med standpunkt** — og begrunn. Ta et valg; ikke «alt har for- og bakdeler».
|
||||||
|
|
||||||
|
<div class="callout callout--eksempel"><span class="callout__label">Typisk case: oljeselskap + CSRD</span><div><em>«Du er bærekraftsansvarlig i et oljeselskap underlagt CSRD. Hvordan tilnærmer du deg?»</em> → <strong>Verktøy:</strong> dobbel vesentlighet. <strong>Teori:</strong> stakeholder-mapping (myndigheter = avgjørende, NGO-er = krevende/avhengig). <strong>Prosess:</strong> de 5 stegene (PIRVO). <strong>Strategi:</strong> CSV — koble grønn omstilling til konkurranseevne (Equinor). <strong>Kritisk blikk:</strong> grønnvasking, degrowth-perspektiv, sterk vs. svak bærekraft.</div></div>
|
||||||
|
|
||||||
|
### Formuleringer som hever karakteren
|
||||||
|
|
||||||
|
- Definér først: «Med X menes …»
|
||||||
|
- Vis spekteret: «På den ene siden … på den andre siden …»
|
||||||
|
- Koble teori til praksis: «Dette kan illustreres med …»
|
||||||
|
- Reflekter kritisk: «En innvending er …»
|
||||||
|
- Konkluder med substans — ta et standpunkt.
|
||||||
|
|
||||||
|
<div class="callout callout--huske"><span class="callout__label">Sluttsjekk</span><div>Hvert svar bør ha: <strong>navngitt teoretiker + årstall</strong>, <strong>ett konkret eksempel</strong>, og <strong>klar struktur</strong> (definer → forklar → eksempel → reflekter). Det er forskjellen på C og A.</div></div>
|
||||||
28
server.ps1
28
server.ps1
@@ -9,16 +9,36 @@ param(
|
|||||||
[string]$Root = "."
|
[string]$Root = "."
|
||||||
)
|
)
|
||||||
|
|
||||||
Add-Type -AssemblyName System.Web
|
# Krasj ikke stille: vis full feil og stopp pent.
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
# Merk: vi bruker [System.Uri]::UnescapeDataString for URL-dekoding i stedet
|
||||||
|
# for System.Web.HttpUtility. System.Web er ikke tilgjengelig i PowerShell 7
|
||||||
|
# (.NET Core) og kan faile pa enkelte oppsett — det var en kilde til at
|
||||||
|
# vinduet "krasjet umiddelbart". System.Uri finnes i bade PS 5.1 og PS 7.
|
||||||
|
|
||||||
|
try {
|
||||||
|
$RootAbs = (Resolve-Path -LiteralPath $Root -ErrorAction Stop).Path
|
||||||
|
} catch {
|
||||||
|
Write-Host "Fant ikke app-mappen: $Root" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not ([System.Net.HttpListener]::IsSupported)) {
|
||||||
|
Write-Host "HttpListener stottes ikke pa denne maskinen." -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
$RootAbs = (Resolve-Path -LiteralPath $Root).Path
|
|
||||||
$listener = New-Object System.Net.HttpListener
|
$listener = New-Object System.Net.HttpListener
|
||||||
$listener.Prefixes.Add("http://127.0.0.1:$Port/")
|
$listener.Prefixes.Add("http://127.0.0.1:$Port/")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$listener.Start()
|
$listener.Start()
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host "Klarte ikke starte server pa port ${Port}: $($_.Exception.Message)" -ForegroundColor Red
|
Write-Host ""
|
||||||
|
Write-Host " Klarte ikke starte server pa port ${Port}:" -ForegroundColor Red
|
||||||
|
Write-Host " $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
Write-Host " Tips: porten kan vaere opptatt, eller en brannmur/policy blokkerer." -ForegroundColor DarkGray
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +77,7 @@ try {
|
|||||||
$res = $context.Response
|
$res = $context.Response
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$path = [System.Web.HttpUtility]::UrlDecode($req.Url.LocalPath)
|
$path = [System.Uri]::UnescapeDataString($req.Url.LocalPath)
|
||||||
if ([string]::IsNullOrEmpty($path) -or $path -eq '/') { $path = '/index.html' }
|
if ([string]::IsNullOrEmpty($path) -or $path -eq '/') { $path = '/index.html' }
|
||||||
|
|
||||||
# Strip leading slash and normalize
|
# Strip leading slash and normalize
|
||||||
|
|||||||
Reference in New Issue
Block a user