/* AI-CENTRAL — det delade designspråket.
 *
 * Fyra sidor bar var sin kopia av det här, och det är därför de drev isär: en
 * ändring måste göras fyra gånger, och gjordes i praktiken en gång. /hem och
 * /login satt kvar på en GitHub-blå palett i månader medan /session och /admin
 * gick över till den varma; ingen valde det, det bara blev så.
 *
 * Vad som hör hemma här: paletten, och de byggstenar mer än en sida använder.
 * Vad som INTE gör det: en sidas egen layout. /session är en app med sidopanel
 * och sticky sidhuvud, /login är ett kort mitt på skärmen — att pressa in dem i
 * en gemensam mall vore att uppfinna en abstraktion åt två fall som inte liknar
 * varandra.
 *
 * Sidorna länkar den här FÖRE sin egen <style>, så en sida som behöver avvika
 * gör det genom att skriva över, inte genom att kopiera alltihop igen.
 */

/* --- paletten --------------------------------------------------------------
 * Unionen av vad de fem sidorna behöver. Variabler bara /session använder
 * (--user, --bot, --diff-*) står här ändå: de hör till samma palett, och en
 * delad fil som utelämnar hälften av färgerna är en delad fil man slutar tro på.
 */
/* ACCENTEN ÄR MÄTTAD SEDAN 2026-08-06, på ägarens uttryckliga val efter en
 * referensbild (mörk dashboard, en enda stark orange, nästan svart golv).
 *
 * Härledd, inte ögonmätt ur bilden: terracottans EGEN kulör behölls (h≈15–17°)
 * och mättnaden drogs upp till referensens nivå. Det är därför den känns som
 * samma produkt och inte som ett färgbyte — hue är identiteten, mättnad är
 * temperaturen.
 *
 *     ljus  #c2593a  (h14 s54 l49)  ->  #c43d08  (h17 s92 l40)
 *     mörk  #d97757  (h15 s63 l60)  ->  #f55414  (h17 s92 l52)
 *
 * VARJE PAR ÄR KONTRASTMÄTT, inte antaget (WCAG AA = 4,5:1 för text):
 *     mörk  accent på --bg          5,70:1      ink på --bg        16,74:1
 *           accent på --panel       5,26:1      muted på --bg       7,60:1
 *           --user-ink på accent    5,55:1
 *     ljus  accent på --panel       5,23:1      vit på accent       5,23:1
 *           accent på --bg          4,88:1      muted på --bg       5,33:1
 * Den ljusa accenten ligger på l40 och inte l42: l42 gav 4,49:1 mot --bg, vilket
 * missar AA med två hundradelar. Ett värde som nästan klarar gränsen är ett värde
 * som inte klarar den.
 */
/* CRYPTO/DEFI-UTTRYCKET, 2026-08-06 (KVAR-7 steg 0b). Ägaren: "lite mer crypto
 * känsla i det hela, den känns väldigt stel nu", "tänk dig en crypto lab sida".
 *
 * RADEN ÄR "Bitcoin DeFi (Mobile)" i designdatabasens `styles.csv`, och den är
 * en nästan exakt träff: dess accenter är #F7931A och #EA580C, och plattformens
 * valda #f55414 ligger mellan dem. Färgen var alltså redan rätt; det var resten
 * av stilen som saknades.
 *
 * TVÅ SAKER RADEN SÄGER SOM PLANEN INTE CITERADE, och båda styr vad som gick
 * att göra:
 *
 *   "Light Mode ✗ — Dark-only".  Stilen HAR ingen ljus variant. Golvet, ytorna
 *   och guldet nedan är därför mörka lägets ensamma; det ljusa läget behåller
 *   sin palett och får bara det som är FORM (radie, piller, gradient, glas),
 *   inte det som är kulör. En stil som är mörk-bara, påtvingad ett ljust läge,
 *   är inte den stilen — det är en sida med olässbar text.
 *
 *   "Space Grotesk / Inter / JetBrains Mono".  Tre webbtypsnitt. Den här
 *   plattformen har ingen CDN någonstans, körs offline och nås från ägarens
 *   egen server; ett typsnittsanrop vore produktens första externa beroende.
 *   Systemstacken nedan står kvar av exakt det skälet den redan stod kvar.
 */
/* MÖRKT ÄR STANDARD SEDAN 2026-08-06, och det är ägarens beslut efter ett fynd
 * som var mitt fel att inte ha gjort tidigare.
 *
 * VAD SOM HÄNDE. Sex PR:er i rad byggde crypto/DeFi-uttrycket och ägaren sa
 * varje gång att ingenting kändes annorlunda. Förklaringen låg i den här filen,
 * skriven av mig i #189: raden i designdatabasen är "Light Mode ✗ — Dark-only",
 * så golvet, ytorna och guldet gjordes till mörka lägets ensamma. Ägaren sitter
 * i LJUST läge. Han hade alltså aldrig sett arbetet — han fick vita kort med en
 * mörkorange siffra, och varenda skärmdump jag visade honom var mörk.
 *
 * Regel 0.15 säger: kontrollera vilken kod som producerade siffran. Samma sak
 * gäller vilken MILJÖ mottagaren står i. Jag mätte min egen.
 *
 * Och hans egen referensbild — den som accenten härleddes ur — var en mörk
 * dashboard. Smakinputen var mörk hela tiden.
 *
 * HUR DET FUNGERAR NU. `:root` bär det mörka, alltid, oavsett vad telefonen
 * säger. `prefers-color-scheme` frågas inte längre: en produkt vars enda
 * genomarbetade identitet är mörk ska inte visa sin svagare halva åt den vars
 * OS råkar stå på ljust. Ljust läge finns kvar bakom `[data-theme="light"]`,
 * satt av växeln i sidopanelen och sparad per webbläsare.
 *
 * /login får ingen växel: den laddar inte nav.js (med avsikt — se sidopanelens
 * not) och renderas därför alltid mörk. En inloggningsruta är fem sekunder av
 * en session, och alternativet vore att lägga temalogik i en sida som medvetet
 * hålls tom före inloggning.
 */
:root {
  /* Command Center cyber floor (2026-09-19). Claudes MÅL, inte den äldre
     void `#030304` / panel `#0f1115` som redan låg live. Blåsvart golv
     `#0B0F19` + yta `#121826` ger HUD-läsning utan OLED-#000. Kontrastmätt:
     ink 16,49:1 · muted 7,49:1 · accent 5,62:1 · ok `#22D96F` 10,23:1 mot golvet.
     Accenten (orange) behålls — identiteten; golvet är det som byter karaktär. */
  --bg: #0B0F19; --panel: #121826; --ink: #f0eee6; --muted: #a3a29d;
  /* ULTRA-THIN BORDERS. Kalla linjer mot blåsvart golv — inte varm grå. */
  --line: rgba(148,163,184,.22); --accent: #f55414; --ok: #22D96F; --warn: #e0a33e;
  /* EGEN TON FÖR DET OÅTERKALLELIGA, och inte `--warn`. Mätt mot ny panel
     `#121826`: 4,53:1 — över AA, knappt; mörka inte vidare utan omräkning. */
  --danger: #e5484d;
  --chip: #2e1c12; --chip-ink: #ffa878; --code-bg: #0a0e18; --hover: #1a2233;
  --bar-bg: #1a2233;
  --accent-gold: #ffd600;
  --grad-cta: linear-gradient(135deg, #ea580c, #f7931a);
  --grad-fig: linear-gradient(165deg, #f55414, #ffd600);
  --glass: rgba(11, 15, 25, .94);
  --on-accent: #180f08;
  --user: var(--accent); --user-ink: var(--on-accent); --bot: #121826; --side: #080c14;
  --diff-add-bg: rgba(34,217,111,.14); --diff-add-ink: #22D96F;
  --diff-del-bg: rgba(248,81,73,.16); --diff-del-ink: #f85149;
  --lift: 0 1px 2px rgba(0,0,0,.55), 0 8px 28px rgba(0,0,0,.40);
  --lift-strong: 0 2px 6px rgba(0,0,0,.50), 0 14px 36px rgba(0,0,0,.48);
  --glow: 0 2px 14px rgba(245,84,20,.30);
  --glow-lift: 0 4px 22px rgba(247,147,26,.42);
  /* HUD-lager — scan/grid/status. Inte layout; bara atmosfär och statusmarkörer. */
  --hud-line: rgba(34, 217, 111, .22);
  --hud-dim: rgba(148, 163, 184, .12);
  --scan-grid-size: 48px;
  /* Atmosfär / overlay — literals only here; call sites use var(--…). */
  --glow-wash: rgba(245, 84, 20, .14);
  --ok-wash: rgba(34, 217, 111, .06);
  --grid-line: rgba(15, 23, 42, .04);
  --scan-line: rgba(255, 255, 255, .12);
  --accent-soft: #e8dfd0;
  --drawer-shadow: rgba(0, 0, 0, .25);
  --overlay: rgba(0, 0, 0, .4);
  --scrim: rgba(0, 0, 0, .35);
  --scrim-soft: rgba(0, 0, 0, .28);
  --scrim-hard: rgba(0, 0, 0, .94);
  --scrim-lift: rgba(0, 0, 0, .55);
  --scrim-sheet: rgba(0, 0, 0, .18);
  --glass-mini: rgba(255, 255, 255, .1);
  --glass-mini-border: rgba(255, 255, 255, .35);
  --warn-wash: rgba(217, 119, 6, .14);
  --white: #fff;
  /* GitHub-knapp (varumärkesfärger — måste skiljas från accenten). */
  --github: #24292f;
  --github-muted: #30363d;
  --github-on-dark: #26241f;
  /* Aktiveringskartans tre banor — meningsbärande state-signaler. */
  --amap-schema: #F7931A;
  --amap-session: #3B82F6;
  --amap-packs: #14B8A6;
  --amap-panel: #0c1526;
}

/* LJUST LÄGE — opt-in, via växeln i sidopanelen. Behållet och inte raderat:
 * ägaren valde "mörkt som standard + knapp", inte "ta bort ljust".
 */
:root[data-theme="light"] {
  --bg: #f6f7f9; --panel: #fff; --ink: #1a1d21; --muted: #5f6773;
  --line: #e5e7eb; --accent: #c43d08; --ok: #16a34a; --warn: #d97706;
  /* Mörkare röd än mörka lägets: #e5484d mot en ljus yta är för svag för text.
     Mätt: #c62a2f ger 5,57:1 mot ytan. Siffran stod först som "5,0:1" — den var
     gissad ur minnet och är nu räknad, av `test_ui_scales.py`. */
  --danger: #c62a2f;
  --chip: #ffece2; --chip-ink: #9c3b12; --code-bg: #f3f4f6; --hover: #f0f2f5;
  --bar-bg: #ece9e4;
  /* GULD, ljusa lägets. Databasens --accent-gold är #FFD600 och det är mätt
     oanvändbart mot en ljus yta: 1,41:1 mot #fff. #946100 ger 4,94:1 mot --bg
     och 5,29:1 mot --panel — samma kulör, dragen ner till där den syns.
     (#a16207 gav 4,59:1 och valdes bort: palettens egen regel säger att ett
     värde som NÄSTAN klarar gränsen är ett värde som inte klarar den.) */
  --accent-gold: #946100;
  /* CTA-GRADIENTEN. Databasen vill ha #EA580C -> #F7931A. I ljust läge är
     etiketten vit, och vitt mot den LJUSA änden mäter 2,30:1 — det är precis
     den fällan KVAR-7 säger ska kontrolleras FÖRE, inte efter. Ljusa lägets
     gradient håller sig därför i den mörka halvan: vitt mot #8f2c06 är 8,30:1
     och mot #c43d08 5,23:1, båda över AA för en 14px-etikett. */
  --grad-cta: linear-gradient(135deg, #8f2c06, #c43d08);
  --grad-fig: linear-gradient(165deg, #c43d08, #946100);
  /* Glasytan bakom navigationen. Alfat är läsbarhetens, inte effektens — se
     den långa noten vid #sidebar. */
  --glass: rgba(252, 252, 253, .94);
  /* Text that sits ON the accent. It is a TOKEN and not `#fff` at each call site
     because the answer stops being white the moment the accent gets brighter —
     which is exactly what happened here: white on the dark scheme's #f55414
     measures 3,41:1 and fails AA for a 14px button label. Four buttons carried a
     hardcoded `color: #fff` and all four would have shipped that. */
  --on-accent: #fff;
  --user: var(--accent); --user-ink: var(--on-accent); --bot: #f2f0ec; --side: #fbfaf8;
  --diff-add-bg: #e6ffed; --diff-add-ink: #22863a;
  --diff-del-bg: #ffeef0; --diff-del-ink: #b31d28;
  --lift: 0 1px 2px rgba(16,18,20,.05), 0 4px 14px rgba(16,18,20,.05);
  --lift-strong: 0 2px 6px rgba(16,18,20,.08), 0 12px 28px rgba(16,18,20,.10);
  --glow: 0 2px 12px rgba(196,61,8,.26);
  --glow-lift: 0 4px 20px rgba(196,61,8,.38);
  --glow-wash: rgba(196, 61, 8, .08);
  --ok-wash: rgba(34, 217, 111, .06);
  --grid-line: rgba(15, 23, 42, .04);
  --scan-line: rgba(0, 0, 0, .08);
  --accent-soft: #e8dfd0;
  --drawer-shadow: rgba(0, 0, 0, .18);
  --overlay: rgba(0, 0, 0, .35);
  --scrim: rgba(0, 0, 0, .35);
  --scrim-soft: rgba(0, 0, 0, .28);
  --scrim-hard: rgba(0, 0, 0, .88);
  --scrim-lift: rgba(0, 0, 0, .4);
  --scrim-sheet: rgba(0, 0, 0, .12);
  --glass-mini: rgba(255, 255, 255, .55);
  --glass-mini-border: rgba(0, 0, 0, .2);
  --warn-wash: rgba(217, 119, 6, .14);
  --white: #fff;
  --github: #24292f;
  --github-muted: #30363d;
  --github-on-dark: #26241f;
  --amap-schema: #F7931A;
  --amap-session: #3B82F6;
  --amap-packs: #14B8A6;
  --amap-panel: #0c1526;
}

/* --- form, rytm och rörelse -------------------------------------------------
 * Tokens, not values sprinkled through the file. Radii were 12/8/7/4 across
 * five pages with nothing deciding which; the scale below is what makes a card
 * and a button look like they were drawn by the same hand.
 *
 * `--ease` is the design database's recommendation for this product class
 * (developer tools, pro dashboards): cubic-bezier(.16,1,.3,1) — fast out of the
 * gate, long settle. Every transition in the shared layer uses it so motion is
 * one gesture rather than five.
 *
 * FONTS: brödtext är system (ingen CDN — offline på ägarens telefon). Rubriker
 * får en egen display-stack (`--font-display`) så h1/h2/panelnamn skiljer sig
 * från body utan extern webfont.
 */
:root {
  /* Cyber HUD-hörn (2026-09-19): Claudes mål 6px — skarpa paneler, inte
     mjuka 24px-kort. Pillerknappar behåller `--radius-pill`. */
  --radius: 6px;           /* cards, panels, sheets */
  --radius-sm: 4px;        /* inputs, chips that are not pills */
  --radius-xs: 2px;        /* inline code, tiny marks */
  --radius-pill: 999px;    /* knappar — `--radius-pill` ur samma rad */

  /* EN TYPOGRAFISK SKALA, för att det inte fanns någon. Allt låg mellan 12,5 och
     15px, vilket är varför varje sida läste som en enda gråmassa: en rubrik, en
     etikett och ett mätvärde vägde exakt lika mycket. En skala ÄR hierarkin.

     SEX STEG, VALDA UR MÄTNINGEN OCH INTE UR SMAK (plan 5a). Tokens fanns redan
     — och 16 hårdkodade px-storlekar låg BREDVID dem i 83 deklarationer. En
     skala som bara gäller där någon råkade använda den är ingen skala.
     Klustren i mätningen är 10-11, 12-13.5, 14-15.5, 16-18, 19-22, 26-29, och
     stegen nedan sitter mitt i vart och ett. Ingen värdeförändring är större än
     3px, och den enda som är det är det stora mätvärdet (34→29), som fanns i
     TVÅ storlekar för samma sorts tal.

     SJU TJOCKLEKAR BLEV FYRA. 620, 640 och 650 förekom en gång var. Ingen
     VÄLJER 640 — man landar där genom att knuffa 600 tills något ser bättre ut
     och lämnar kvar knuffen. 400/500/600/700 är kvar; de tre knuffarna är
     avrundade till 600.

     Att lägga till ett steg här är en ändring i EN fil, och det är meningen. */
  --fs-micro: 11px;        /* versaletiketter, det minsta som får finnas */
  --fs-label: 13px;        /* etiketter, meta, det som stödjer */
  --fs-body: 15px;         /* brödtext */
  --fs-lead: 17px;         /* panelrubrik */
  --fs-title: 29px;        /* sidrubrik — Claude re-PASS: 22 → ~28–30 */
  --fs-fig: 29px;          /* ett mätvärde som är sidans poäng */

  /* EN AVSTÅNDSSKALA, av samma skäl och med samma metod. Mätt: 30 unika
     px-värden i padding/margin/gap över 273 förekomster, utan inbördes
     förhållande — 8, 9 och 10 användes 48, 16 och 37 gånger var, vilket är tre
     värden för ett avstånd. Sex steg, och de fyra minsta är oförändrade, så den
     täta känslan sidan bygger på rörs inte.

     10px LIGGER MITT EMELLAN 8 och 12 och avrundas NEDÅT, till 8. Det är den
     enda kännbara ändringen — 42 ställen drar ihop sig 2px — och den gick åt
     rätt håll av sig själv: raden säger täthet, och en oavgjord avrundning som
     lossar hellre än drar ihop hade gjort sidan luftigare än den ska vara. Det
     här stycket sa först "10 och 11 tas upp av 12"; utfallet blev det motsatta,
     och stycket är rättat efter mätningen i stället för tvärtom.

     Steg 6 (20px) tar upp 15-24. Värden över 24px är SIDLAYOUT och inte
     komponentavstånd — de står kvar och är räknade. */
  --sp-1: 2px;
  --sp-2: 4px;
  --sp-3: 6px;
  --sp-4: 8px;
  --sp-5: 12px;
  --sp-6: 20px;
  --ease: cubic-bezier(.16, 1, .3, 1);
  /* Asymmetrisk reveal: in 200ms, ut 140ms (Outputs, media-gap, backdrop). */
  --dur-enter: 200ms;
  --dur-exit: 140ms;
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
  /* Rubrik/display — självhostad Space Grotesk (/static/fonts/*.woff2, OFL,
     ingen CDN). FÖRSTA FÖRSÖKET HÄR VAR ORBITRON ÖVERALLT — ägarens rättning:
     "typsnittet skall fortfarande vara modern, inte scifi". Space Grotesk är
     mellanläget: samma tekniska, geometriska karaktär som gör kartan
     distinkt, men läsbar som rubrik i normal text i stället för en
     HUD-etikett. Bara 500/600/700 finns självhostade: rubriker och
     etiketter, aldrig brödtext (`--font-sans` är oförändrad där).
     Kartan behåller sin EGEN Orbitron via `--font-amap` — den är ett
     instrument-HUD, inte en sida, och fick sitt typsnitt innan den här
     ändringen fanns. Ägarens rättning gällde sidrubriker, inte kartan. */
  --font-display: "Space Grotesk", "Avenir Next", Avenir, "Century Gothic",
                  Futura, "Trebuchet MS", var(--font-sans);
  --font-amap: "Orbitron", var(--font-display);
}

/* Självhostad Space Grotesk — /static/fonts/*.woff2 (OFL). Alla sidrubriker. */
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/space-grotesk-500.woff2") format("woff2");
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/fonts/space-grotesk-600.woff2") format("woff2");
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/space-grotesk-700.woff2") format("woff2");
}

/* Självhostad Orbitron — /static/fonts/*.woff2 (OFL). Bara amap-etiketter. */
@font-face {
  font-family: "Orbitron";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/orbitron-500.woff2") format("woff2");
}
@font-face {
  font-family: "Orbitron";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/fonts/orbitron-600.woff2") format("woff2");
}
@font-face {
  font-family: "Orbitron";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/orbitron-700.woff2") format("woff2");
}

/* --- grunden --------------------------------------------------------------- */
:root { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }
* { box-sizing: border-box; }
/* GRAFPAPPERET ÄR BORTA (ägarens ord: "rutigt bakom", "ser gammal ut" — två
   gånger, mot riktiga skärmdumpar). Rutnätet var tänkt som atmosfär, inte
   innehåll, men på en ljus, tät sida (Filer, Admin, Schema) blev det synligt
   överallt — det ENDA en ny besökare faktiskt märker. Linear/Vercel/Raycast,
   referensen den här paletten redan är byggd mot, har aldrig ett rutnät
   under sina paneler: en enda disciplinerad accent, ingen bakgrundstextur.
   Kvar är bara den mjuka gløden — djup utan ett mönster som läser som
   diagram-papper. */
body { margin: 0; background: var(--bg); color: var(--ink);
  font: 15px/1.55 var(--font-sans); -webkit-font-smoothing: antialiased;
  background-image:
    radial-gradient(1200px 600px at 12% -10%, var(--glow-wash), transparent 55%),
    radial-gradient(900px 500px at 90% 0%, var(--ok-wash), transparent 50%);
  background-attachment: fixed; }
:root[data-theme="light"] body {
  background-image:
    radial-gradient(1000px 480px at 10% -8%, var(--glow-wash), transparent 55%);
}
@media (prefers-reduced-motion: reduce) {
  body { background-attachment: scroll; }
  .panel, .outputs-backdrop, #outputs-rail, .media-gap, .sheet, .sheet-backdrop {
    transition: none !important;
  }
}

header { padding: var(--sp-6) var(--sp-6); border-bottom: 1px solid var(--line); }
header h1 { margin: 0; font-family: var(--font-display); font-size: var(--fs-title);
  font-weight: 600; letter-spacing: -0.035em; }
header p { margin: var(--sp-2) 0 0; color: var(--muted); font-size: var(--fs-label); }
header a { color: var(--accent); text-decoration: none; }
/* Utan den här ärver varje länk utanför sidhuvudet webbläsarens blå — på sidor
   som just bytt bort blått. Admin-spärrens enda länk gjorde precis det. */
main a, .gate a { color: var(--accent); text-decoration: none; }
/* `main` betyder HÄR "sidans textspalt". En sida där main i stället är en
   rullyta måste skriva över de två första — `max-width` + `margin: 0 auto` på
   ett flex-barn krymper det till innehållets bredd, vilket inte syns i en
   skärmdump och märks direkt med musen. /session gör precis det, och säger
   varför. Det är den enda regeln i den här filen med den fällan. */
main { max-width: 1080px; margin: 0 auto; padding: var(--sp-6) var(--sp-5) 48px; }

/* --- paneler --------------------------------------------------------------- */
/* KORTEN SKA VARA FÖREMÅL, inte textblock med en kant runt. Panelen låg tio
   enheter från golvet (#171716 mot #0d0d0c) och läste som samma yta; det var
   ramen som gjorde kortet, inte ytan. Nu bär ytan det, och `::before` lägger en
   ljusreflex längs överkanten — samma knep som referensbilden använder för att
   få kort att se upplyfta ut i stället för inklistrade.
   Primär = mer djup (radius + skugga). `.panel.secondary` är plattare. */
.panel { position: relative; background: var(--panel); border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 2px); padding: var(--sp-6) var(--sp-6);
  box-shadow: var(--lift-strong);
  transition: box-shadow .3s var(--ease), border-color .3s var(--ease); }
.panel.secondary { border-radius: var(--radius); box-shadow: var(--lift); }
/* INGEN `.panel:has(.status-dot.live)`-regel, med flit — provad och kastad.
   `.status-dot.live` sätts på flera panelrubriker (Hem "Senaste sessioner",
   "Kom igång") som ren vanestyling, aldrig kopplat till om något faktiskt
   uppdateras just då. En regel här gjorde VARJE sådan panel permanent grön,
   vilket gör signalen meningslös — allt glöder, inget säger "det här
   händer nu". `.hud-cell`s version nedan är kvar: de dotarna sätts av JS
   utifrån verkligt tillstånd (Admin Aktivitet, Schema-status), inte som
   statisk markup. Skärmdump avslöjade skillnaden, inte läsning. */
.panel::before { content: ''; position: absolute; left: 0; right: 0; top: 0;
  height: 1px; background: linear-gradient(90deg, transparent,
    var(--scan-line), transparent); pointer-events: none; }
/* Gemener och full bläckfärg: rubriken ska bära hierarki, inte skrika. Versala
   muted rubriker var vad /hem och /admin hade, och nio paneler som alla skriker
   lika högt är nio paneler utan ordning. */
.panel h2 { margin: 0 0 var(--sp-5); font-family: var(--font-display);
  font-size: var(--fs-lead); font-weight: 600; color: var(--ink);
  letter-spacing: -0.03em; display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: baseline; }
.panel h2 .sub { font-family: var(--font-sans); font-size: var(--fs-label); font-weight: 400;
  color: var(--muted); letter-spacing: 0; }
h1, h2 { font-family: var(--font-display); letter-spacing: -0.03em; }

/* --- Command Center HUD (delade byggstenar) --------------------------------
 * Tokens ovan byter hela produkten. Klasserna här är OPT-IN: Hem/Admin/Session/
 * Schema/Filer plockar in celler, kickers och status-dots utan att bygga om
 * schemalagd körning (ingen scheduled_runs-ombyggnad).
 */
.scan-grid { position: relative; }
.hud-cell {
  position: relative; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--sp-5) var(--sp-5);
  box-shadow: var(--lift);
  transition: box-shadow .3s var(--ease), border-color .3s var(--ease);
}
.hud-cell::before {
  content: ''; position: absolute; left: 0; top: var(--sp-4); bottom: var(--sp-4);
  width: 2px; background: var(--accent); border-radius: var(--radius-xs);
  opacity: .85;
}
/* KORTET GLÖDER NÄR DET FAKTISKT ÄR LIVE, inte bara den 8px-prick som satt
   ensam om att bära det. Aktiveringskartans noder lyser som en ring runt
   HELA noden när den är aktiv — samma signal hörde aldrig hem på resten av
   appens kort, där "live" bara var en punkt i hörnet ingen märkte förrän de
   letade. Samma gröna ton `.status-dot.live` redan använder, bara buren av
   hela ytan i stället för 8 pixlar. `:has()` — inget nytt JS, inget nytt
   attribut, samma dot som redan sätts. */
.hud-cell:has(.status-dot.live) {
  border-color: color-mix(in srgb, var(--ok) 45%, var(--line));
  box-shadow: var(--lift), 0 0 0 1px color-mix(in srgb, var(--ok) 20%, transparent),
    0 0 24px color-mix(in srgb, var(--ok) 16%, transparent);
}
/* `.hud-label` är OPT-IN utanför cellen också (Hem-paneler, Admin Nu-h2).
   Under `.hud-cell` är den cellens etikett; utanför cellen samma typografi. */
.hud-label {
  font-size: var(--fs-micro); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 var(--sp-2);
}
.hud-cell .hud-value {
  font-family: var(--font-mono); font-size: var(--fs-fig); font-weight: 600;
  line-height: 1.1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.status-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: var(--radius-pill);
  background: var(--muted); vertical-align: middle; margin-right: var(--sp-2);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--muted) 25%, transparent);
}
.status-dot.ok { background: var(--ok);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--ok) 28%, transparent); }
.status-dot.warn { background: var(--warn);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--warn) 28%, transparent); }
.status-dot.danger { background: var(--danger);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 28%, transparent); }
.status-dot.live {
  background: var(--ok);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--ok) 28%, transparent);
  animation: hud-pulse 1.6s var(--ease) infinite;
}
@keyframes hud-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .45; }
}
@media (prefers-reduced-motion: reduce) {
  .status-dot.live { animation: none; }
}
.hud-kicker {
  font-family: var(--font-mono); font-size: var(--fs-micro);
  letter-spacing: .14em; text-transform: uppercase; color: var(--accent);
  margin: 0 0 var(--sp-2);
}

/* --- Instrument-lager (crypto/finance balansstil) --------------------------
 * OPT-IN ovanpå `.hud-cell`. Admin Nu / Verktyg / Historik och Filer-scope
 * plockar in `.instr` — knappar, formulär och navigering rörs inte.
 *
 * Tre mönster, EN modul (plan A): balanskort+sparkline, gauge-båge, coin-rad.
 * Paletten är plattformens Bitcoin-DeFi-tokens (--accent / --accent-gold /
 * --ok / --warn), inte en parallel guld/Orbitron-varumärke. `--fs-micro`
 * (11px) är golvet.
 */
.hud-cell.instr {
  padding: var(--sp-5) var(--sp-5) var(--sp-4);
  background:
    linear-gradient(165deg,
      color-mix(in srgb, var(--accent) 7%, var(--panel)) 0%,
      var(--panel) 42%);
}
.hud-cell.instr::before {
  background: var(--grad-cta); opacity: 1;
}
.hud-cell.instr.is-warn::before {
  background: var(--warn);
}
.hud-cell.instr.is-unmeasured {
  background: var(--panel);
}
.hud-cell.instr.is-unmeasured::before {
  background: var(--muted); opacity: .45;
}
.hud-cell.instr .hud-value {
  font-size: var(--fs-fig);
}
.instr-balance .instr-viz {
  margin-top: var(--sp-4);
  min-height: 0;
}
/* Sparkline: trendstreck under saldot. Tom behållare = ingen historik (inga
   påhittade punkter). aria-hidden: siffran ovan är den tillgängliga källan. */
.instr-spark {
  display: block; width: 100%; height: 28px;
  color: var(--accent);
}
.instr-spark polyline {
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.instr-spark .instr-spark-fill {
  stroke: none; fill: color-mix(in srgb, var(--accent) 18%, transparent);
}
/* Gauge-båge: andel mot tak (spend). Färger i zoner, inte bara en gradient-
   fyllning - chart-regeln "not color alone" täcks av pct-texten i cellen. */
.instr-gauge {
  display: block; width: 100%; max-width: 9.5rem; height: auto;
  margin: var(--sp-3) 0 0; color: var(--accent);
}
.instr-gauge .instr-gauge-track {
  fill: none; stroke: var(--bar-bg); stroke-width: 8; stroke-linecap: round;
}
.instr-gauge .instr-gauge-fill {
  fill: none; stroke: var(--accent); stroke-width: 8; stroke-linecap: round;
}
.instr-gauge.is-warn .instr-gauge-fill { stroke: var(--warn); }
.instr-gauge.is-ok .instr-gauge-fill { stroke: var(--ok); }
.instr-gauge .instr-gauge-pct {
  fill: var(--muted); font-family: var(--font-mono); font-size: var(--fs-micro);
  letter-spacing: .04em;
}
/* Coin-rad: färgad cirkel + namn + värde. Ersätter `.prow`/`.cnt` där listan
   är ett mätinstrument (mönster, drift, verktygsfördelning). */
.instr-row {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-3) 0; border-bottom: 1px dashed var(--line);
  min-width: 0;
}
.instr-row:last-child { border-bottom: 0; }
.instr-coin {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: var(--radius-pill);
  background: var(--instr-coin, var(--accent));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--instr-coin, var(--accent)) 28%, transparent);
}
.instr-row-body { flex: 1 1 auto; min-width: 0; }
.instr-row-name {
  display: block; font-size: var(--fs-label); color: var(--ink);
  overflow-wrap: anywhere; line-height: 1.35;
}
.instr-row-name .muted { font-size: var(--fs-micro); }
.instr-row-val {
  flex: 0 0 auto; font-family: var(--font-mono); font-size: var(--fs-label);
  font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink);
  letter-spacing: -.01em;
}
.instr-row.is-hot .instr-row-val { color: var(--warn); }
.instr-row.is-hot .instr-coin {
  background: var(--warn);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--warn) 28%, transparent);
}
/* Mono-chips: små saldorader (Filer antal, Session-liknande steg/tid-rad). */
.instr-chips {
  display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 0 var(--sp-4);
}
h2 .instr-chips, .sub.instr-chips {
  display: inline-flex; margin: 0 0 0 var(--sp-3); vertical-align: middle;
  max-width: 100%;
}
.instr-chip {
  display: inline-flex; align-items: baseline; gap: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums; letter-spacing: .02em;
  color: var(--ink); background: color-mix(in srgb, var(--panel) 70%, var(--bg));
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: var(--sp-2) var(--sp-3); line-height: 1.2;
}
.instr-chip .instr-chip-k {
  color: var(--muted); text-transform: uppercase; letter-spacing: .1em;
}
/* Historik-sammanfattning: samma instr-yta på `.ts-cell` utan att riva hörnen. */
.ts-cell.instr {
  background:
    linear-gradient(165deg,
      color-mix(in srgb, var(--accent) 6%, var(--bg)) 0%,
      var(--bg) 50%);
}
.ts-cell.instr .ts-v { font-size: var(--fs-fig); }

/* Preview vs Produktion - två tydliga filer, aldrig en blandad grön/röd.
   Används av Schema sec-blockerare (PR-mergevakt). Samma .instr-yta. */
.instr-lanes {
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
  margin: var(--sp-3) 0 var(--sp-4);
}
.instr-lanes .hud-cell.instr { margin: 0; }
.instr-lane-prod::before {
  background: var(--accent);
}
.instr-lane-preview::before {
  background: var(--accent-gold);
}
.instr-lane-meta {
  margin: var(--sp-3) 0 0; font-family: var(--font-mono);
  font-size: var(--fs-micro); color: var(--muted); letter-spacing: .02em;
  overflow-wrap: anywhere;
}
.instr-lane-actions {
  margin-top: var(--sp-4); display: flex; flex-wrap: wrap;
  gap: var(--sp-3); align-items: center;
}

.row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-5);
  padding: var(--sp-3) 0; border-bottom: 1px dashed var(--line); }
.row:last-child { border-bottom: 0; }
.k { color: var(--muted); }
/* Mono for FIGURES, sans for prose — and `.v` is both. The design database's
   dashboard pairing says "code for data, sans for labels", and applying it to
   every `.v` was a misread that only a screenshot caught: half the values on
   /admin are sentences ("nej — sidor kan inte öppnas"), and a sentence set in
   bold mono reads worse than it did before. Tabular figures without the face
   change is what `.v` actually needs; `.v.fig` opts in where the value really
   is a number. */
.v { font-variant-numeric: tabular-nums; text-align: right; max-width: 62%;
  overflow-wrap: anywhere; }
.v.fig { font-family: var(--font-mono); font-size: var(--fs-label); }
/* Ett tal som är sidans poäng, inte en cell i en tabell. `.v.fig` är för
   rader; det här är för brickor och nyckeltal, och det är skillnaden mellan
   en instrumentpanel och en lista. */
/* `--fs-fig-lg` (34px) FÖLL UT UR SKALAN, och att den fanns var självt fyndet:
   samma sorts tal — ett mätvärde som är sidans poäng — ritades i 34px här och i
   29px på brickorna. Två storlekar för en betydelse. Nu `--fs-fig`, en gång.
   Att den här raden inte följde med när steget togs bort fångades av
   `test_every_token_the_stylesheets_use_is_defined`: en odefinierad token tar
   HELA sin deklaration med sig, tyst, och siffran hade renderats i ärvd
   brödtextstorlek utan att någon fick veta. */
.fig-lg { font-family: var(--font-mono); font-size: var(--fs-fig); font-weight: 600;
  line-height: 1.05; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }

/* GRADIENTTEXT PÅ SALDON, ur databasens checklista ("Gradient text on
   balances", maskad orange->guld). Plattformens egen data HAR formen: "Spend
   idag 0/200" är ett saldo, "Stegbudget 5/20" är en mätare mot sitt tak.
   Kontrasten är gradientens SÄMSTA ände, inte dess medelvärde: mörkt läge
   #f55414 = 6,05:1 mot golvet, ljust #c43d08 = 4,88:1 mot --bg. Båda över AA
   även om ett 29px fet tal bara kräver 3,0:1.

   OPT-IN, OCH DET ÄR HELA POÄNGEN (regel 0.27). Maskning sätter `color:
   transparent`, så den ÄTER varje betydelse som bor i färg. Brickorna på /admin
   har två: `.is-warn` färgar talet varningsgult och `.is-unmeasured` gråar ut
   ett "—" som inte är ett värde. Ett svep över alla tal hade raderat båda
   signalerna utan att något såg trasigt ut. Därför bär anropsstället klassen,
   och bara där talet ÄR ett mätt saldo.

   Första försöket satte det här på `.fig-lg` — som ingen sida använder. Det
   hade blivit exakt vad regel 0.23 varnar för: en token som ändras och en
   skärm som ser likadan ut.

   `@supports` är inte artighet. Faller maskningen bort blir texten
   `color: transparent` mot ingenting — ett osynligt nyckeltal, vilket är värre
   än ett omaskat. Reserven är att ingenting händer alls. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .fig-grad { background: var(--grad-fig); -webkit-background-clip: text;
    background-clip: text; color: transparent; }
}
.fig-md { font-family: var(--font-mono); font-size: var(--fs-fig); font-weight: 600;
  line-height: 1.1; letter-spacing: -0.015em; font-variant-numeric: tabular-nums; }

/* --- små ting -------------------------------------------------------------- */
.chip { display: inline-block; background: var(--chip); color: var(--chip-ink);
  border-radius: 999px; padding: var(--sp-1) var(--sp-4); margin: var(--sp-1) var(--sp-2) var(--sp-1) 0; font-size: var(--fs-label); }
a.chip-link { text-decoration: none; }
a.chip-link:hover { filter: brightness(1.08); }
.ok { color: var(--ok); font-weight: 600; }
.warn { color: var(--warn); font-weight: 600; }
.muted { color: var(--muted); font-size: var(--fs-label); }
.err { color: var(--warn); font-size: var(--fs-label); }
code { background: var(--code-bg); padding: var(--sp-1) var(--sp-3); border-radius: var(--radius-xs);
  font-family: var(--font-mono); font-size: var(--fs-label); }

/* Mätaren är den andra halvan av "saldo": ett tal mot sitt tak. Gradienten är
   samma två färger som CTA:n, så en full mätare och en tryckbar knapp läser som
   samma system. */
.bar { height: 10px; background: var(--bar-bg); border-radius: var(--radius-pill);
  overflow: hidden; margin-top: var(--sp-2); }
.bar > span { display: block; height: 100%; background: var(--grad-cta); }
.meter { margin: var(--sp-4) 0; }
.meter .label { display: flex; justify-content: space-between; font-size: var(--fs-label); }

/* --- knappar och fält ------------------------------------------------------ */
/* PILLERKNAPPAR MED GRADIENT OCH GLÖD — tre rader ur databasens `Effects`:
   "pill buttons with glowing shadows" och "Bitcoin orange/gold gradients for
   CTAs". Etikettens kontrast mot gradientens BÅDA ändar står mätt i paletten
   ovan; det är den enda kontrollen den här formen kräver och den är gjord. */
/* `min-height: 44px` + `inline-flex`/`center`: mätt i webbläsaren, `.btn`s
   egen padding (`--sp-4` `--sp-6` = 8px/16px) gav en knapp på ~32px hög —
   under tryckyte-golvet (44px) på varje sida som använder den delade
   klassen. En regel HÄR, inte en fix per sida — annars är det exakt den
   drift den här filens egen inledande kommentar varnar för. */
.btn { display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: var(--sp-4) var(--sp-6); border-radius: var(--radius-pill);
  background: var(--grad-cta); color: var(--on-accent); font-size: var(--fs-label); font-weight: 600;
  border: 0; box-shadow: var(--glow); transition: transform .18s var(--ease),
  box-shadow .18s var(--ease), filter .18s var(--ease); }
.btn:hover { filter: brightness(1.06); box-shadow: var(--glow-lift); }
/* Press moves. On a phone this is the only feedback that the tap registered
   before the network answers. */
.btn:active { transform: scale(.97); }
/* `background-image: none` och inte bara `background`: en gradient är en
   bakgrundsBILD, och kortformen ovan sätter den. Att bara skriva
   `background: transparent` här hade lämnat gradienten kvar under den — en
   spökknapp med full CTA-fyllning. Uppmätt i webbläsaren, inte befarat. */
.btn.ghost { background: transparent; background-image: none; color: var(--accent);
  border: 1px solid var(--line); box-shadow: none; }
button.mini { background: transparent; border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-5); font-size: var(--fs-micro); cursor: pointer;
  transition: color .18s var(--ease), border-color .18s var(--ease); }
button.mini:hover { color: var(--accent); border-color: var(--accent); }
button.mini:disabled { opacity: .55; cursor: default; }
/* DET SOM INTE GÅR ATT ÅNGRA SKA INTE SE UT SOM DET SOM GÅR (plan 6c).
   "Radera" och "Redigera" satt bredvid varandra som `class="mini"` och
   renderades tecken för tecken likadant. Alla fyra hade redan ett `confirm()`,
   vilket är rätt och otillräckligt: dialogen kommer EFTER klicket, och admin
   nås från telefonen i fickan där ett felklick är en tumme.

   Efter `:hover`-raden ovan, inte före: annars vinner den generella regeln på
   samma specificitet och en raderingsknapp blir orange när man håller på den. */
button.mini.danger { color: var(--danger); border-color: var(--danger); }
/* Samma beslut för den stora knappen. De två i Säkerhet var `.btn` med
   `style="background:var(--warn)"` — FYLLDA, alltså formen sidan använder för
   sin primära handling, i den färg som redan betyder "något är fel". Ihålig och
   röd säger i stället: detta är en utväg, inte vägen. */
.btn.danger { background: transparent; background-image: none;
  color: var(--danger); border: 1px solid var(--danger); box-shadow: none; }
.btn.danger:hover { filter: none; box-shadow: none;
  background: color-mix(in srgb, var(--danger) 12%, transparent); }
button.mini.danger:hover { color: var(--danger); border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, transparent); }
/* Kryssrutorna var WEBBLÄSARENS BLÅ. /admin ritade fyra av dem rakt ovanför en
   orange knapp, och blått är den enda färg den här paletten inte innehåller —
   det var det mest iögonfallande i hela vyn och ingen hade satt det, det ärvdes.
   Två sidor satte redan `accent-color` på sina egna rutor (`.fd-pick`,
   `.switch input`); det här är samma rad flyttad dit den gäller alla fem. */
input[type=checkbox], input[type=radio] { accent-color: var(--accent); }
input[type=text] { width: 100%; padding: var(--sp-4) var(--sp-5); border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--bg); color: var(--ink);
  font: inherit; font-size: var(--fs-label); transition: border-color .18s var(--ease); }
/* FOKUSRINGEN TOGS BORT OCH ERSATTES MED EN KANTFÄRG. Det är prioritet 1 i
   designdatabasens egen tabell ("Removing focus rings" står som antimönster
   under Accessibility, CRITICAL), och det bröt två regler med en rad: den som
   säger att tangentbordsfokus ska synas, och `color-not-decorative-only` — en
   kant som redan fanns och bara byter kulör är färg som ensam bär betydelse,
   och för den som inte skiljer kulörerna finns ingen signal alls.

   `:focus-visible` och inte `:focus`: ringen ska synas för den som tabbar, inte
   runt fältet någon just klickade i. Kantfärgen behålls — den är nu det
   sekundära, redundanta beskedet i stället för det enda. */
input[type=text]:focus { border-color: var(--accent); }

/* SAMMA RING RUNT ALLT SOM GÅR ATT TABBA TILL, och tidigare fanns den bara runt
   textfält (plan 5c). Allt annat — knappar, flikar, länkar, `<summary>`,
   kryssrutor — lämnades åt webbläsarens egen ring, som ritas i systemets färg
   mot en yta den inte vet något om. Den syns ibland. "Ibland" är inte ett
   fokusläge; det är ett fokusläge man upptäcker att man tappat först när man
   inte längre vet var man är på sidan.

   `:focus-visible` av samma skäl som raden ovan: ringen är till för den som
   tabbar, inte runt knappen någon just tryckte på med tummen. */
:where(a, button, summary, select, textarea, input, [tabindex]):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: inherit;
}
/* `:where()` bär noll specificitet, så den här raden kan inte vinna över en
   komponents egen fokusstil — den fyller bara i där ingen finns. Det är också
   varför den inte behöver upprepa `input[type=text]`-regeln nedan. */
input[type=text]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* --- utfällningar ----------------------------------------------------------
 * <details>/<summary> i stället för egen JS: tangentbordsnåbart, fungerar utan
 * skript, och kan inte hamna i otakt med en egen öppen/stängd-flagga.
 */
.fold { border-bottom: 1px dashed var(--line); }
.fold:last-child { border-bottom: 0; }
.fold > summary { list-style: none; cursor: pointer; padding: var(--sp-4) 0;
  display: flex; gap: var(--sp-4); align-items: baseline; }
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::after { content: '›'; margin-left: auto; color: var(--muted);
  font-size: var(--fs-lead); line-height: 1; transition: transform .22s var(--ease); }
.fold[open] > summary::after { transform: rotate(90deg); }
.fold .why { padding: 0 var(--sp-2) var(--sp-5) var(--sp-6); color: var(--muted); font-size: var(--fs-label); }
.flat { padding: var(--sp-4) 0; display: flex; gap: var(--sp-4); align-items: baseline;
  border-bottom: 1px dashed var(--line); }
.flat:last-child { border-bottom: 0; }
.mark { flex: 0 0 12px; color: var(--muted); }
.mark.warn { color: var(--warn); }
.say { flex: 1; min-width: 0; overflow-wrap: anywhere; }

.more { margin-top: var(--sp-4); }
.more > summary { list-style: none; cursor: pointer; color: var(--muted); font-size: var(--fs-label); }
.more > summary::-webkit-details-marker { display: none; }
.more > summary::before { content: '+ '; }
.more[open] > summary::before { content: '– '; }

/* --- listor med fakta/rader som går att åtgärda ---------------------------- */
.fact { display: flex; justify-content: space-between; gap: var(--sp-4); align-items: flex-start;
  padding: var(--sp-4) 0; border-bottom: 1px dashed var(--line); }
.fact:last-child { border-bottom: 0; }
.fact-main { flex: 1; min-width: 0; }
.fact-text { overflow-wrap: anywhere; }
.tag { display: inline-block; margin-left: var(--sp-4); background: var(--chip); color: var(--chip-ink);
  border-radius: 999px; padding: var(--sp-1) var(--sp-4); font-size: var(--fs-micro); vertical-align: 1px; }
.fact-actions { flex: 0 0 auto; display: flex; gap: var(--sp-3); }
.editbox { width: 100%; min-height: 54px; padding: var(--sp-3) var(--sp-4); border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--bg); color: var(--ink); font: inherit;
  font-size: var(--fs-label); resize: vertical; }
.ask { display: flex; gap: var(--sp-4); margin-bottom: var(--sp-5); }
.ask button { flex: 0 0 auto; }
.dist { color: var(--muted); font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-label); margin-right: var(--sp-4); }

/* --- spärrsidan ------------------------------------------------------------ */
.gate { max-width: 560px; margin: 40px auto; text-align: center; color: var(--muted); }

/* --- turens instrument -----------------------------------------------------
 * Ägaren, 2026-08-06, efter att designomgången i #189 inte kändes: "allt ser
 * fortfarande samma ut" och sedan "mätare osv, lite mer häftigt, sci fi
 * känslor". Regel 0.23 säger varför #189 inte räckte — den bytte YTOR (golv,
 * radie, gradient) och lät STRUKTUREN stå. En ny radie på ett kort i samma
 * layout är samma kort.
 *
 * Det här är strukturen. Ingen ny färg: varenda värde nedan är en token som
 * redan fanns.
 *
 * EN MODUL, TVÅ PLACERINGAR. Ägaren såg två förslag och sa "jag gillar den
 * sista men A verkar vara optimal" — A var en instrumentremsa på telefon, den
 * sista en högerskena på skrivbord. Det är samma information i olika bredder,
 * så det är byggt som en sak: remsa som standard, skena när det finns plats.
 * Två komponenter hade drivit isär, vilket är precis det sidopanelen ovanför
 * bevisar.
 *
 * HUD-HÖRNEN är ur designdatabasens "Cyberpunk Mobile HUD"-rad, som är den enda
 * raden i basen som svarar mot "sci fi". Dess FÄRGER är neongrönt och magenta
 * och togs INTE: accenten är härledd ur ägarens egen referensbild och kulören
 * är identiteten. Det som togs är formen — hörnfästen, mono-versaler på
 * etiketter, hårfina mätare, siffran som det tyngsta på skärmen.
 */
.turnstate { display: grid; gap: var(--sp-1); background: var(--line);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-bottom: 1px solid var(--line); }
.turnstate[hidden] { display: none; }
/* Hero-status FÖRE de fyra talen. Tröskeln (30s) är hårdkodad i JS — statusen
   räknas alltid ur idle, aldrig en fast "OK"-text. */
.ts-hero {
  grid-column: 1 / -1; background: var(--bg); padding: var(--sp-3) var(--sp-5);
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .06em; display: flex; align-items: center; gap: var(--sp-2);
}
.ts-hero.is-ok { color: var(--ok); }
.ts-hero.is-stale { color: var(--danger); }
/* En komponent: `#turnstate` och kartans statsrad delar `.hud-cell.instr`. */
.turnstate > .hud-cell.instr { margin: 0; min-width: 0; }
.ts-cell { position: relative; background: var(--bg); padding: var(--sp-4) var(--sp-5) var(--sp-4); min-width: 0; }
/* Hörnfästen, ritade och inte bilder: två kanter per pseudo-element. */
.ts-cell::before, .ts-cell::after { content: ''; position: absolute; width: 7px; height: 7px;
  border-color: var(--accent); opacity: .5; }
.ts-cell::before { left: 5px; top: 5px; border-left: 1px solid; border-top: 1px solid; }
.ts-cell::after { right: 5px; bottom: 5px; border-right: 1px solid; border-bottom: 1px solid; }
.ts-k { display: block; font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); }
.ts-v { display: block; font-family: var(--font-mono); font-size: var(--fs-lead); font-weight: 600;
  letter-spacing: -.02em; color: var(--ink); margin-top: var(--sp-1); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-v small { font-size: var(--fs-micro); color: var(--muted); font-weight: 500; }
.ts-g { height: 3px; margin-top: var(--sp-3); background: var(--bar-bg); overflow: hidden; }
.ts-g > i { display: block; height: 100%; background: var(--grad-cta);
  transition: width .3s var(--ease); }
/* Turen som lever. Pricken är REDUNDANT — värdet står i klartext bredvid. */
.ts-cell.is-live .ts-v { color: var(--accent); }
.ts-cell.is-live .ts-k::after { content: ''; display: inline-block; width: 5px; height: 5px;
  border-radius: var(--radius-pill); background: var(--accent); margin-left: var(--sp-3);
  vertical-align: 1px; animation: runpulse 1.4s var(--ease) infinite; }
@media (prefers-reduced-motion: reduce) { .ts-cell.is-live .ts-k::after { animation: none; } }
/* KVAR 4.5: när turen landat ska panelen säga det, inte bara sluta pulsera.
   Banderollen spanar hela bredden så de fyra cellerna behåller sin layout. */
.ts-done { grid-column: 1 / -1; background: var(--bg); color: var(--ok);
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; padding: var(--sp-3) var(--sp-5);
  border-bottom: 1px solid var(--line); }
.turnstate.is-done { border-bottom-color: var(--ok); }
@media (max-width: 560px) { .turnstate { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Pinnad plan-checklista — innehållet är alltid riktig todo-data. */
.plan-check {
  max-width: 760px; margin: 0 auto var(--sp-4); padding: var(--sp-4) var(--sp-5);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
}
.plan-check[hidden] { display: none; }
.plan-check-h {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 var(--sp-3);
}
.plan-check ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.plan-check li {
  font-size: var(--fs-body); color: var(--ink); display: flex; gap: var(--sp-3);
  align-items: flex-start; line-height: 1.35;
}
.plan-check li::before {
  content: ''; flex: 0 0 8px; width: 8px; height: 8px; margin-top: .35em;
  border-radius: var(--radius-xs); border: 1px solid var(--muted);
}
.plan-check li.is-completed { color: var(--muted); text-decoration: line-through; }
.plan-check li.is-completed::before {
  background: var(--ok); border-color: var(--ok);
}
.plan-check li.is-in_progress::before {
  background: var(--accent); border-color: var(--accent);
}
.plan-check li.is-failed::before {
  background: var(--danger); border-color: var(--danger);
}

/* Delegate-kort — samma kortklass-mönster som granskningen: fråga synlig direkt,
   svar när det landar. */
.delegate {
  align-self: stretch; background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--amap-session); border-radius: var(--radius);
  padding: var(--sp-5) var(--sp-6); margin: var(--sp-4) 0; max-width: 40rem;
}
.delegate h4 {
  margin: 0 0 var(--sp-3); font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: .06em; text-transform: uppercase; color: var(--amap-session);
}
.delegate h4 span { color: var(--muted); font-weight: 500; text-transform: none; letter-spacing: 0; }
.delegate-q { color: var(--ink); margin-bottom: var(--sp-4); white-space: pre-wrap; }
.delegate-a {
  border-top: 1px solid var(--line); padding-top: var(--sp-4); color: var(--ink);
  white-space: pre-wrap; font-size: var(--fs-body);
}
.delegate-a.is-pending { color: var(--muted); font-style: italic; }
.delegate-a.is-failed { color: var(--danger); }

/* --- den delade sidopanelen ------------------------------------------------
 * Markupen byggs av /static/nav.js — den kan inte bo här, och den kan inte bo i
 * fyra kopior. Det som bor här är UTSEENDET, av samma skäl som paletten gör det:
 * en panel som ritas på fyra sidor får inte se ut på fyra sätt.
 *
 * `.has-nav` sätts på <html> av nav.js vid inläsning. Utan den klassen — /login
 * är den enda sidan som saknar panelen, med avsikt — gäller ingenting härnedan,
 * och sidan får ingen tom marginal där en panel inte finns.
 *
 * PANELEN ÄR `fixed`, INTE EN KOLUMN. Det är valt: fyra sidor med fyra olika
 * layouter (en app med sticky sidhuvud, tre dokumentspalter) skulle annars alla
 * behöva byggas om till flex-rader med ett omslutande element. `fixed` + en
 * vänstermarginal på `body` rör inte en enda av dem — panelen läggs BREDVID det
 * som redan finns.
 */
:root { --side-w: 264px; }
.has-nav body { padding-left: var(--side-w); }

/* GLASMORF NAV, ur databasens checklista ("BlurView nav implemented",
   `--blur-intensity: 20`) — men på den opacitet en SKÄRMDUMP tvingade fram, inte
   den raden föreslår.

   VAD SOM HÄNDE, och det är därför alfat står där det står. Första försöket satte
   `--glass` på .72, vilket är den vanliga glasmorf-nivån. På telefon ligger
   panelen som en låda ÖVER transkriptet, och bilden visade sidans text rakt
   igenom destinationerna: "Hem" och "Admin" låg ovanpå halva meningar.

   Och det avgörande i bilden: den genomlysande texten var SKARP, inte suddig.
   Alltså komponerades `backdrop-filter` inte alls — bara genomskinligheten bet.
   `@supports` fångar inte det: webbläsaren SÄGER att den kan, och låter bli när
   den saknar drivrutinen. Databasen flaggar exakt det ("blur effects require
   native driver"), och en effekt vars säkerhet HÄNGER på att suddet faktiskt
   körs är en effekt som blir oläslig på den maskin som inte kan.

   Därför: alfat är satt så att panelen är läsbar HELT UTAN sudd, och suddet är
   en förstärkning ovanpå — inte det som räddar den. Det är fortfarande glas
   (ytan tar upp kulören under sig, kanten frostar), men det är glas som inte
   kan gå sönder tyst. `prefers-reduced-transparency` stänger av resten. */
#sidebar { position: fixed; z-index: 30; top: 0; left: 0; width: var(--side-w);
  height: 100vh; display: flex; flex-direction: column;
  background: var(--side); border-right: 1px solid var(--line); }
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  #sidebar { background: var(--glass);
    -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
}
@media (prefers-reduced-transparency: reduce) {
  #sidebar { background: var(--side);
    -webkit-backdrop-filter: none; backdrop-filter: none; }
}
.side-head { padding: var(--sp-5); }
#newchat { width: 100%; padding: var(--sp-4) var(--sp-5); border: 0; border-radius: var(--radius-sm);
  background: var(--accent); color: var(--on-accent); font: inherit; font-size: var(--fs-label);
  font-weight: 600; cursor: pointer; box-shadow: var(--glow);
  transition: filter .18s var(--ease), transform .18s var(--ease); }
#newchat:hover { filter: brightness(1.06); }
#newchat:active { transform: scale(.97); }

/* Destinationerna överst, alltid samma ordning, alltid samma fyra. */
.side-dest { display: flex; flex-direction: column; padding: var(--sp-2) var(--sp-4) var(--sp-4); }
.side-dest .dest { display: block; padding: var(--sp-3) var(--sp-4); border-radius: var(--radius-sm);
  color: var(--ink); text-decoration: none; font-size: var(--fs-label);
  transition: background .18s var(--ease), color .18s var(--ease); }
.side-dest .dest.sub { margin-left: var(--sp-5); font-size: var(--fs-label); color: var(--muted); }
.side-dest .dest:hover { background: var(--hover); }
/* VAR DU ÄR, markerat med mer än färg. En rad som bara byter kulör är färg som
   ensam bär betydelse — samma antimönster som fokusringen var, och det står
   som CRITICAL i designdatabasens tillgänglighetstabell. Kanten till vänster är
   det redundanta beskedet, och `aria-current` är det för en skärmläsare. */
.side-dest .dest[aria-current="page"] { background: var(--chip); color: var(--chip-ink);
  font-weight: 600; box-shadow: inset 2px 0 0 var(--accent); }

/* Temaväxeln. En INSTÄLLNING, längst ner, tydligt skild från destinationerna
   överst — de säger vart man kan gå, den här säger hur det ser ut medan man är
   där. Textknapp och ingen ikon: en sol/måne kräver att man vet vilken av dem
   som betyder "nuvarande" och vilken som betyder "byt till". */
.side-foot { margin-top: auto; padding: var(--sp-4) var(--sp-4); border-top: 1px solid var(--line); }
#themetoggle { width: 100%; padding: var(--sp-4) var(--sp-4); border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: transparent; color: var(--muted);
  font: inherit; font-size: var(--fs-label); cursor: pointer;
  transition: color .18s var(--ease), border-color .18s var(--ease); }
#themetoggle:hover { color: var(--accent); border-color: var(--accent); }

.side-label { padding: var(--sp-4) var(--sp-6) var(--sp-2); border-top: 1px solid var(--line);
  color: var(--muted); font-size: var(--fs-label); }
#conv-search {
  display: block; width: calc(100% - 2 * var(--sp-4)); margin: 0 var(--sp-4) var(--sp-2);
  box-sizing: border-box; font: inherit; font-size: var(--fs-label);
  padding: var(--sp-3) var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--ink);
}
#conv-search::placeholder { color: var(--muted); }
#conv-list { flex: 1; overflow-y: auto; padding: var(--sp-2) var(--sp-4) var(--sp-4); }
.side-empty { padding: var(--sp-4) var(--sp-4); color: var(--muted); font-size: var(--fs-label); }
.conv { position: relative; display: block; width: 100%; text-align: left;
  border: 1px solid transparent; background: transparent; color: inherit; font: inherit;
  border-radius: var(--radius-sm); padding: var(--sp-4) 26px var(--sp-4) var(--sp-4); margin-bottom: var(--sp-1);
  cursor: pointer; }
.conv:hover { background: var(--hover); }
.conv.active { background: var(--chip); border-color: var(--line); }
.conv-title, .conv-meta { display: block; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.conv-title { font-size: var(--fs-label); font-weight: 600; }
.conv-meta { font-size: var(--fs-micro); color: var(--muted); }
.conv-del { position: absolute; right: 6px; top: 7px; color: var(--muted);
  font-size: var(--fs-micro); opacity: 0; transition: opacity .18s var(--ease); }
.conv:hover .conv-del, .conv.active .conv-del { opacity: 1; }
.conv-del:hover { color: var(--warn); }

/* Lådan bakom ☰ på telefon — samma på varje sida, vilket är hela poängen. */
#menu { display: none; background: transparent; border: 1px solid var(--line);
  color: var(--ink); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-4); font-size: var(--fs-body);
  line-height: 1.2; cursor: pointer; }
/* Reserven för en sida utan sidhuvud. Ingen av dagens fyra tar den vägen. */
#menu.nav-float { position: fixed; z-index: 31; top: 10px; left: 10px; background: var(--panel); }
#overlay { display: none; }

/* Turen som är i luften, i listan du kommer tillbaka genom — en LIVE-POSITION,
   och databasen ber om "pulsing status indicators" för precis den. /session har
   redan en på `.tool.live`; den här är samma signal på den enda andra plats där
   något faktiskt lever, så att en tur som kör syns i panelen på alla fyra
   sidorna och inte bara på den man råkar stå på.

   Pricken är REDUNDANT, inte ensam: chippet säger "kör" i text också. En puls
   som ensam bär betydelsen är otillgänglig, och den stängs dessutom av nedan. */
.run-chip { display: inline-block; background: var(--chip); color: var(--chip-ink);
  border-radius: var(--radius-pill); padding: 0 var(--sp-3); font-size: var(--fs-micro); font-weight: 600; }
.run-chip::before { content: ''; display: inline-block; width: 5px; height: 5px;
  border-radius: var(--radius-pill); background: currentColor; margin-right: var(--sp-2);
  vertical-align: 1px; animation: runpulse 1.4s var(--ease) infinite; }
/* Bakgrundsjakt / schema-chip: ingen puls — klar eller schemalagd, inte "i luften". */
.run-chip.auto-chip { background: var(--accent-soft); color: var(--ink); }
.run-chip.auto-chip::before { display: none; }
@keyframes runpulse { 0%, 100% { opacity: 1; } 50% { opacity: .2; } }
@media (prefers-reduced-motion: reduce) { .run-chip::before { animation: none; } }

@media (max-width: 860px) {
  .has-nav body { padding-left: 0; }
  #menu { display: inline-block; }
  #sidebar { transform: translateX(-100%); transition: transform .2s var(--ease);
    box-shadow: 0 0 30px var(--drawer-shadow); }
  body.drawer-open #sidebar { transform: translateX(0); }
  body.drawer-open #overlay { display: block; position: fixed; inset: 0; z-index: 20;
    background: var(--overlay); }
  /* De tre dokumentsidornas sidhuvud är ett block: rubrik, sedan en rad text.
     Knappen prependas i det, och utan den här regeln lägger den sig PÅ EN EGEN
     RAD ovanför rubriken. Klassen sätts av nav.js bara när knappen faktiskt
     hamnade direkt i ett <header> — /session pekar ut sin egen rad i stället, och
     ska inte få den här layouten pådyvlad. */
  header.nav-in-header { display: flex; flex-wrap: wrap; align-items: center;
    column-gap: var(--sp-4); }
  header.nav-in-header > h1 { flex: 1 1 auto; min-width: 0; }
  header.nav-in-header > p, header.nav-in-header > .cta { flex: 1 1 100%; }
}
