
  :root {
    /* VEKTORIA-teema 2026-05-21 — Claude-tyylinen vaalea + selkeä */
    --logo: #0F1F3A;        /* Hiili — VAIN logo (säilyy tummana) */
    --navy: #334155;        /* Slate 700 — header-ankkuri, vasen logoblokki */
    --blue: #1E2F4A;        /* Tumma laventeli — pää-painikkeen TEKSTI */
    --leaf-deep: #0F1F3A;   /* Hover-tilan tumma teksti */
    --bark-warm: #64748B;   /* Slate 500 — toissijainen aksentti */
    --bark-light: #F5F2EB;  /* Pellava — toissijainen pohja */
    --orange: var(--blue); /* deprekoitu alias — käytä var(--blue); migroitu 2026-06-04 (audit) */
    /* 2026-06-10: YHTENÄISET vektorivalinta-värit — KAIKKI valintapinnat (modaali +
       inline-paneeli + lasso) käyttävät NÄITÄ → ei enää eri värejä eri modaaleissa.
       Valittu = sininen, hylätty = himmeä punainen. */
    --vec-sel: #1565c0;                       /* valittu (stroke) */
    --vec-sel-fill: rgba(21,101,192,0.30);    /* valittu täytetty (fill) */
    --vec-sel-fill-soft: rgba(21,101,192,0.06);/* valittu polygon-pohja (hailakka) */
    --vec-dis: #ef9a9a;                       /* hylätty (stroke) */
    --vec-dis-fill: rgba(239,154,154,0.16);   /* hylätty täytetty (fill) */
    /* 2026-06-28: canvas-overlay-aksentti — KAIKKI vaalean PDF:n PÄÄLLE piirretyt apuviivat
       (mittausluonnos, valintalaatikon reuna, vyöhykkeet, kahvat, kattavuus). EI sama kuin
       --blue: --blue kääntyy tummassa lähes valkoiseksi → katoaisi vaalealta PDF:ltä. Tämä
       pysyy aina näkyvänä (vaalea: ink kuten ennen, tumma: sininen). */
    --canvas-accent: var(--blue);
    /* B3 painike-värit (laventeli-sininen tausta + tumma teksti) */
    --btn-bg: #DBE5F0;      /* Pää-painike: pehmeä laventeli-sininen pohja */
    --btn-bg-hover: #C2D2E5; /* Hover: tummempi laventeli */
    --btn-fg: #1E2F4A;      /* Pää-painikkeen teksti: tumma laventeli */
    --btn-sec-bg: #F1F5F9;  /* Sekundääri-painike: vaalea harmaa pohja */
    --btn-sec-fg: #475569;  /* Sekundääri-painikkeen teksti: keskiharmaa */
    /* 2026-05-21: Lämmin vaalea Claude-tyyli */
    --bg: #FBFAF7;          /* Lämmin valkoinen — päätausta (oli #FAFAF7) */
    --panel: #FFFFFF;       /* Puhdas valkoinen — kortit, modaalit */
    --panel-soft: #FAFBFC;  /* Hyvin vaalea harmaa — input-taustat, info-laatikot */
    --border: #E8EAEC;      /* Lämpimämpi reuna (oli #E8EDF3 viileä sini) */
    --border-soft: #F1F3F5; /* Vielä vaaleampi jakaja (uusi) */
    --text: #1A1A1F;        /* Lähes musta — pääteksti (parempi kontrasti kuin #0F1F3A:lla) */
    --text-soft: #475569;   /* Tumma harmaa — toissijainen teksti (uusi token) */
    --text-muted: #64748B;  /* Slate 500 — vihjetekstit (tummennettu: oli #64748B) */
    --text-faint: #64748B;  /* Pikkutekstit — tummennettu AA-kontrastiin 2026-06-04 (oli #64748B) */
    --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
    /* ── Radius-skaala 2026-06-02 (P2 token-foundation) ───────────────────────
       Arvot = olemassa olevat valtaklusterit → migraatio on ARVO-IDENTTINEN
       (ei yhtä pikseliä muutu). Yksi totuuden lähde tuleville säädöille.
       Pitkä häntä (3/5/7/9/11/14/16/18/24px, pill 99/999) jätetty ennalleen. */
    --radius-sm: 4px;    /* pienet kontrollit, chipit, swatchit */
    --radius-md: 6px;    /* napit, inputit, popover-rivit */
    --radius-lg: 8px;    /* kortit, paneelit */
    --radius-xl: 10px;   /* isommat kortit */
    --radius-2xl: 12px;  /* modaalit, isot pinnat */
    /* ── DESIGN-SYSTEM-PERUSTA 2026-06-04 (UI-audit Vaihe 2a) ─────────────────
       ADDITIIVINEN: yksi totuuden lähde väleille, tekstikoolle, varjoille,
       kerroksille ja statusväreille. Olemassa olevia literaaleja EI vielä
       migroitu (tehdään per-pinta + verifioiden) → tämä lisäys ei muuta pikseliä. */
    /* Välistys (4px-pohja) */
    --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px; --space-6: 32px;
    /* Tekstikoko-skaala (olemassa olevat klusterit) */
    --text-xs: 11px; --text-sm: 12px; --text-base: 13px; --text-md: 14px; --text-lg: 16px; --text-xl: 18px;
    /* Varjot (kohotasot) */
    --shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
    --shadow-md: 0 4px 16px rgba(0,0,0,0.10);
    --shadow-lg: 0 20px 60px rgba(0,0,0,0.30), 0 4px 16px rgba(0,0,0,0.10);
    /* Kerrokset (z-index — yksi hallittu pino) */
    --z-base: 1; --z-sticky: 100; --z-topbar: 200; --z-popover: 500; --z-modal: 1100; --z-toast: 10000;
    /* Semanttiset statusvärit (+ pehmeä tausta-variantti) */
    --success: #16a34a; --success-soft: #dcfce7;
    --warn: #d97706;    --warn-soft: #fef3c7;
    --danger: #dc2626;  --danger-soft: #fee2e2;
    --info: #2563eb;    --info-soft: #dbeafe;
    /* 12px palautetekstin AA-parit. Dark-teema vaihtaa etu-/taustavärit
       keskenään 01-base-11.css:ssä; kontrasti säilyy kaikissa kolmessa ≥7.7:1. */
    --success-feedback-bg: #dcfce7; --success-feedback-fg: #14532d;
    --warn-feedback-bg: #fef3c7;    --warn-feedback-fg: #713f12;
    --danger-feedback-bg: #fee2e2;  --danger-feedback-fg: #7f1d1d;
    /* Vuorovaikutus */
    --focus: var(--blue);  /* :focus-visible-renkaan väri */
    --hit-min: 32px;       /* min. kohdekoko (WCAG 2.5.8) — klikkialan laajennukseen */
    /* ── Motion-tokenit (2026-07-10, Emil Kowalski -auditti) ──
       Säännöt: UI-animaatiot ≤300ms; exit nopeampi kuin enter; EI ease-in:iä
       (tuntuu hitaalta); pikanäppäintoiminnot EIVÄT animoidu koskaan.
       HUOM: :root-tasolla tarkoituksella — motion EI ole teemakohtaista
       (teemat body.theme-* -lohkoissa eivät ylikirjoita näitä). */
    --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
    --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
    --dur-press: 160ms;   /* painalluspalaute */
    --dur-pop: 180ms;     /* tooltipit, pienet popoverit */
    --dur-panel: 240ms;   /* modaalit, liukupaneelit */
  }
  * { box-sizing: border-box; }
  body {
    margin: 0;
    /* 2026-05-21: kattavampi font-stack — Inter ensisijaisesti, sitten OS-fontit, sitten generic.
       -apple-system + BlinkMacSystemFont = San Francisco macOS:lla, Segoe UI Windowsilla. */
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
    font-feature-settings: 'cv11', 'ss01'; /* Inter: parannettu numerojen + suomenkielen luettavuus */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    background: var(--bg);
    color: var(--text);
    height: 100vh;
    display: flex;
    flex-direction: column;
  }
  /* ── Näppäimistöfokus (a11y) 2026-06-02 ──────────────────────────────────
     Globaali :focus-visible-rengas. Näkyy VAIN näppäimistönavigoinnissa
     (Tab), ei hiiriklikissä → ei muuta hiiri-ulkoasua. Korvaa hajanaiset
     outline:none -nollaukset johdonmukaisella aksenttirenkaalla. */
  :focus-visible {
    outline: 2px solid var(--blue);
    outline-offset: 1px;
    border-radius: 3px;
  }
  /* ── .btn — jaettu nappikomponentti 2026-06-04 (UI-audit Vaihe 2b) ──────────
     Yksi nappimalli + variantit + KAIKKI tilat (hover/active/disabled/focus).
     Uudet ja uudistetut pinnat kayttavat tata; vanhat luokat migroidaan
     per-pinta Vaiheessa 3. ADDITIIVINEN — ei vaikuta nykyisiin luokkiin. */
  .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    position: relative; box-sizing: border-box;
    height: 30px; padding: 0 var(--space-3);
    font-family: inherit; font-size: var(--text-sm); font-weight: 600; line-height: 1;
    color: var(--text-soft); background: var(--panel);
    border: 1px solid var(--border); border-radius: var(--radius-md);
    cursor: pointer; white-space: nowrap; user-select: none;
    transition: background .15s ease, border-color .15s ease, color .15s ease, transform .1s ease;
  }
  .btn:hover { border-color: var(--blue); color: var(--blue); }
  .btn:active { transform: translateY(1px); }
  .btn:disabled, .btn[disabled], .btn.is-disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
  .btn svg { width: 14px; height: 14px; stroke: currentColor; flex-shrink: 0; }
  .btn--primary { background: var(--btn-bg); color: var(--btn-fg); border-color: var(--btn-bg); }
  .btn--primary:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); color: var(--btn-fg); }
  .btn--ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
  .btn--ghost:hover { background: var(--panel-soft); border-color: var(--border); color: var(--blue); }
  .btn--danger { color: var(--danger); }
  .btn--danger:hover { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
  .btn--sm { height: 24px; font-size: var(--text-xs); padding: 0 var(--space-2); }
  .btn--icon { width: 30px; padding: 0; }
  .btn--icon.btn--sm { width: 24px; }
  .btn--block { width: 100%; }
  /* Kohdekoko-suoja (WCAG 2.5.8): pienet/ikoni-napit saavat nakymattoman klikkialan */
  .btn--sm::before, .btn--icon::before { content: ''; position: absolute; inset: -4px; border-radius: inherit; }
  /* Hiirikäyttäjälle ei rengasta (selain hoitaa :focus-visible-erottelun) */
  :focus:not(:focus-visible) { outline: none; }
  /* ── Ribbon-header ─────────────────────────────────────────────────────── */
  /* 2026-05-30: lisätty flex-wrap — header sisältö (brand+project+näkymä+työkalut)
     vaatii ~1700px; alle ~1500px näytöillä työkalut-ryhmä valui ulos oikealta.
     Nyt työkalut wrappaavat luonnollisesti alariville (AutoCAD/CAD-tyylinen
     2-rivinen ribbon kun tarpeen), >1700px näytöillä pysyy 1-rivisenä. */
  header {
    background: var(--panel);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 1px 4px rgba(0,0,0,0.07);
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 0;
    flex-shrink: 0;
    min-height: 52px;
  }
  /* 2026-06-04: Ominaisuus-liput (feature flags) — irrotettavat moduulit.
     [data-feature]-merkityt elementit piilotetaan asiakkaan Perus-tasolla (basic).
     Täysi-taso (käyttäjän oma versio) näyttää kaikki. Ks. _initFeatureFlags. */
  .feature-off { display: none !important; }
  /* 2026-06-04: Yläpalkin 3-vyöhykejako (Dokumentti · Työkalut · Näkymä+Projekti) */
  .hdr-zone { display: flex; align-items: center; }
  /* Ylärivi: Dokumentti (vasen) + Näkymä/Projekti (oikea); alarivi: työkalupalkki (keski, oma rivi) */
  #hdr-left { gap: 6px; order: 1; flex: 0 1 auto; min-width: 0; }
  #hdr-right { gap: 6px; order: 2; margin-left: auto; padding-right: 8px; }
  /* 2026-07-12: aina näkyvä kielivalitsin (FI/EN) yläpalkin navy-chromella. Aktiivinen
     segmentti korostetaan aksenttivärillä; wiring 00-i18n.js initLangSwitch (.active). */
  .lang-switch { display: inline-flex; align-items: center; height: 26px; border: 1px solid rgba(255,255,255,0.24); border-radius: 7px; overflow: hidden; flex: 0 0 auto; }
  .lang-switch .lang-switch-btn { border: 0; background: transparent; color: #fff; font-family: inherit; font-size: 11px; font-weight: 700; letter-spacing: .04em; padding: 0 10px; height: 100%; cursor: pointer; opacity: .62; transition: background .12s, opacity .12s; }
  .lang-switch .lang-switch-btn:hover { opacity: .95; background: rgba(255,255,255,0.10); }
  .lang-switch .lang-switch-btn.active { opacity: 1; background: var(--canvas-accent, #1565C0); color: #fff; }
  #hdr-center { order: 3; flex: 1 0 100%; justify-content: flex-start; padding: 3px 8px 1px; border-top: 1px solid var(--border); margin-top: 3px; }
  /* 2026-06-05 Countfire-työkalurivi: YKSI rivi (5 tiiltä). Laske & Mittaa avaavat KELLUVAN
     pystylistan (#lt-subbar-* = overlay-pudotus, ei vie layout-tilaa). Pikanäppäin-merkit data-sckey. */
  #left-tools { position: relative; display: flex; flex-direction: column; gap: 0; padding: 0; border-bottom: 1px solid var(--border); background: var(--panel); flex-shrink: 0; }
  #lt-toprow { display: flex; gap: 4px; padding: 7px 8px; }
  #left-tools .lt-tile { position: relative; flex: 1 1 0; min-width: 0; max-width: none; height: 48px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 4px 2px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); font-family: inherit; font-size: 10.5px; font-weight: 600; color: var(--text); cursor: pointer; text-transform: none; letter-spacing: 0; line-height: 1.05; white-space: nowrap; transition: background .12s, border-color .12s, color .12s, transform var(--dur-press) var(--ease-out); }
  #left-tools .lt-tile:hover { border-color: var(--blue); color: var(--blue); }
  #left-tools .lt-tile svg { width: 18px; height: 18px; stroke: currentColor; flex-shrink: 0; }
  #left-tools .lt-tile.lt-icon-only svg { width: 21px; height: 21px; }
  #left-tools .lt-tile > span:not(.lt-caret) { overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
  #left-tools .lt-tile.active, #left-tools .lt-tile[aria-pressed="true"] { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  /* caret = merkki että tiilellä on alavalikko */
  #left-tools .lt-caret { position: absolute; top: 3px; right: 4px; font-size: 8px; line-height: 1; color: var(--text-muted); transition: transform .12s, color .12s; }
  #left-tools .lt-tile.active .lt-caret { color: var(--blue); }
  #left-tools .lt-tile.lt-open .lt-caret { transform: rotate(180deg); color: var(--blue); }
  /* KELLUVA pystylista (Countfire-pudotus): ikoni + nimi + pikanäppäin-merkki */
  .lt-subbar { position: absolute; z-index: 200; display: none; flex-direction: column; gap: 1px; min-width: 196px; padding: 6px; background: var(--panel); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 10px 28px rgba(20,30,45,.16); }
  /* Pudotuksen otsikko = ryhmän nimi (konteksti: kumman työkalun alivalinnat nämä ovat) */
  .lt-subbar .lt-sub-head { padding: 3px 9px 7px; margin: 0 0 4px; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted); border-bottom: 1px solid var(--border); }
  /* HUOM: kumoa legacy .ribbon-btn-säännön max-width:60px + min-width:42px (rb-dt-työkalut perivät sen) —
     muuten nimi-span litistyy 0-levyiseksi ja vain ikoni + näppäin näkyvät (Symboli/Mittaviiva/Reitti/…). */
  .lt-subbar .lt-sub { display: flex; flex-direction: row; align-items: center; justify-content: flex-start; width: 100%; max-width: none; min-width: 0; height: auto; min-height: 36px; gap: 9px; padding: 7px 10px; border: 1px solid transparent; border-radius: 7px; background: transparent; font-family: inherit; font-size: 12px; font-weight: 600; color: var(--text); cursor: pointer; text-transform: none; letter-spacing: 0; line-height: 1.1; white-space: nowrap; transition: background .1s, color .1s, border-color .1s; }
  /* 2026-07-22: [hidden]-attribuutti ei muuten piiloita .lt-sub-nappia koska display:flex
     yllä voittaa selaimen [hidden]{display:none}. Suora valinta -nappi jäi "harmaana mutta
     näkyviin". Pakotetaan piiloon. */
  .lt-subbar .lt-sub[hidden], [data-direct-selection][hidden] { display: none !important; }
  .lt-subbar .lt-sub:hover { background: #f0f4f8; border-color: transparent; color: var(--text); }
  .lt-subbar .lt-sub svg { width: 16px; height: 16px; stroke: currentColor; flex-shrink: 0; }
  .lt-subbar .lt-sub > span { flex: 1 1 auto; text-align: left; overflow: hidden; text-overflow: ellipsis; }
  /* Pikanäppäin-merkki = PASSIIVINEN vihje (monospace, kuten ohjepaneelin <kbd>), ei näytä napilta */
  .lt-subbar .lt-sub[data-sckey]::after { content: attr(data-sckey); flex: 0 0 auto; margin-left: 10px; font-size: 10px; font-weight: 600; font-family: 'JetBrains Mono', ui-monospace, monospace; color: var(--text-muted); background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; min-width: 18px; text-align: center; }
  .lt-subbar .lt-sub.active, .lt-subbar .lt-sub[aria-pressed="true"] { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  /* 2026-06-08 redesign — "Valitse & tunnista": selkeä hierarkia. Uusi tuote = PÄÄ-toiminto
     (täytetty aksenttinappi); Vapaa rajaus / Suora valinta / Monivalinta = VALINTATAPA-kytkimet
     (iOS-toggle oikealla = yksiselitteinen päällä/pois); Symboli = erillinen työkalu erottimen alla.
     Aktiivitila (.active / aria-pressed) hoidetaan JS:ssä jo → tämä on puhdas CSS/HTML-kerros. */
  .lt-subbar .lt-sub-grouplabel { padding: 9px 9px 3px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); }
  /* 2026-07-25: valintatapa-laajennin (#lt-selmode-toggle) POISTETTU. Se oli
     kuollut kontrolli — 2026-07-19 päätös palautti kytkimet näkyviin ja piilotti
     laajentimen `display:none !important`illa, jolloin .selmode-open ei koskaan
     aktivoitunut. Samalla poistui Lasso (V) kokonaan (käyttäjäpäätös). */
  /* Muokkaustavan selite kytkimen alla: kertoo AINA mitä seuraava rajaus tekee,
     jottei kytkimen tilaa tarvitse päätellä (käyttäjä: "pitää olla selkeämpi"). */
  .lt-subbar .lt-sub-note { padding: 3px 10px 8px; font-size: 10.5px; line-height: 1.45; color: var(--text-soft); }
  /* Persistentti tila-pilli: näkyy kun käyttäjä on kytkenyt EI-OLETUSTILAN (vanha iso
     muokkausikkuna) → vahinkoaktivointi ei jää huomaamatta. Klikkaus palauttaa oletuksen.
     2026-07-25: aiemmin pilli näytti "suora valinta päällä"; kun se on nyt OLETUS,
     pysyvä pilli olisi ollut pelkkää kohinaa → logiikka käännetty. */
  #selmode-indicator { display: none; position: fixed; left: 50%; bottom: 16px;
    transform: translateX(-50%); z-index: 210; padding: 7px 14px; border-radius: 20px;
    background: var(--blue); color: #fff; font-size: 12px; font-weight: 700;
    box-shadow: 0 4px 16px rgba(20,30,45,.28); cursor: pointer;
    align-items: center; gap: 8px; }
  body.modal-select-on #selmode-indicator { display: inline-flex; }
  #selmode-indicator .smi-x { opacity: .8; font-weight: 800; }
  /* 2026-06-25: "Tunnista" (#7) — ikoni samaa väriä kuin muut työkalut (käyttäjäpyyntö:
     sininen erottui liikaa). Erottuvuus tulee nyt "Reittien tunnistus" -ryhmäotsikosta. */
  .lt-subbar .lt-sub-detect svg { color: currentColor; }
  .lt-subbar #new-product-btn.lt-sub-primary { background: var(--btn-bg); color: var(--btn-fg); border-color: transparent; font-weight: 800; min-height: 40px; }
  .lt-subbar #new-product-btn.lt-sub-primary:hover { background: var(--btn-bg-hover); color: var(--btn-fg); }
  .lt-subbar #new-product-btn.lt-sub-primary svg { color: var(--btn-fg); }
  .lt-subbar #new-product-btn.lt-sub-primary[data-sckey]::after { background: rgba(255,255,255,.55); border-color: transparent; color: var(--btn-fg); }
  /* Valintatapa-kytkimet */
  .lt-subbar .lt-sub-toggle::after { display: none; }            /* keycap = reaalielementti .lt-key */
  .lt-subbar .lt-sub .lt-key { flex: 0 0 auto; font-size: 10px; font-weight: 600; font-family: 'JetBrains Mono', ui-monospace, monospace; color: var(--text-muted); background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; min-width: 18px; text-align: center; }
  .lt-subbar .lt-sub .lt-switch { flex: 0 0 auto; width: 30px; height: 18px; border-radius: 9px; background: #cbd5e1; position: relative; transition: background .15s; }
  .lt-subbar .lt-sub .lt-switch::before { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(20,30,45,.3); transition: transform .15s; }
  .lt-subbar .lt-sub-toggle.active, .lt-subbar .lt-sub-toggle[aria-pressed="true"] { background: #f3f7fc; border-color: transparent; color: var(--text); }
  .lt-subbar .lt-sub-toggle.active > span:first-of-type, .lt-subbar .lt-sub-toggle[aria-pressed="true"] > span:first-of-type { color: var(--blue); font-weight: 700; }
  .lt-subbar .lt-sub-toggle.active .lt-switch, .lt-subbar .lt-sub-toggle[aria-pressed="true"] .lt-switch { background: var(--blue); }
  .lt-subbar .lt-sub-toggle.active .lt-switch::before, .lt-subbar .lt-sub-toggle[aria-pressed="true"] .lt-switch::before { transform: translateX(12px); }
  /* 2026-06-05 Countfire: työkalut TUMMAAN pystysuuntaiseen railiin näytön vasempaan reunaan.
     #left-tools siirretty <main>:n suoraksi lapseksi (#tool-rail). Brand-tummat sävyt (ei kirkasta sinistä).
     Flyoutit (.lt-subbar) pysyvät vaaleina + aukeavat railin OIKEALLE (place()-funktio). */
  #tool-rail { order: -2; width: 64px; flex-shrink: 0; background: #0F1F3A; border-right: 1px solid #21314d; display: flex; flex-direction: column; }
  #tool-rail #left-tools { position: relative; flex-direction: column; gap: 0; padding: 0; border-bottom: 0; background: transparent; }
  #tool-rail #lt-toprow { flex-direction: column; gap: 6px; padding: 8px 6px; }
  #tool-rail .lt-tile { flex: 0 0 auto; width: 52px; height: 52px; border: 1px solid transparent; border-radius: 10px; background: transparent; color: #C7D2E2; font-size: 9.5px; gap: 4px; }
  #tool-rail .lt-tile svg { width: 20px; height: 20px; }
  #tool-rail .lt-tile.lt-icon-only svg { width: 22px; height: 22px; }
  #tool-rail .lt-tile:hover { background: #1b2c47; color: #fff; border-color: transparent; }
  #tool-rail .lt-tile.active, #tool-rail .lt-tile[aria-pressed="true"] { background: #1b2c47; color: #fff; border-color: #DBE5F0; }
  /* caret osoittaa OIKEALLE (flyout aukeaa railin oikealle puolelle), kierähtää auki-tilassa */
  #tool-rail .lt-caret { top: 50%; right: 3px; transform: translateY(-50%) rotate(-90deg); color: #8aa0c0; }
  #tool-rail .lt-tile.active .lt-caret { color: #fff; }
  #tool-rail .lt-tile.lt-open .lt-caret { transform: translateY(-50%) rotate(90deg); color: #fff; }
  /* 2026-06-10 TAKSONOMIA (deep-research): 2 PÄÄTYÖKALUA (Laske/Mittaa = .lt-group) erottuvat
     pehmeällä täytöllä; erotin "Apuvälineet"; 3 APUVÄLINETTÄ (.lt-helper) himmeämpinä alla.
     2026-08-02: Laskenta-alue on kolmas .lt-group; vanhoja .lt-helper-irtotiiliä ei enää ole.
     Output-pohjainen malli: Laske=kpl, Mittaa=m/m². Ei kosketa wiringiin (id-pohjainen). */
  /* 2026-08-03 KÄYTTÄJÄPALAUTE "Laske-valikko on aina musta": taksonomiatäyttö oli
     jäänyt merkityksettömäksi JA se söi aktiivitilan.
     (1) Yllä oleva kommentti kertoo että täyttö erotti PÄÄtyökalut apuvälineistä —
         mutta sama kommentti toteaa ettei .lt-helper-tiiliä enää ole. Kaikki kolme
         railitiiltä ovat .lt-group, joten täyttö ei erottanut mitään; se sai vain
         jokaisen tiilen näyttämään pysyvästi painetulta tummalla railillä.
     (2) Tämä sääntö tulee MYÖHEMMIN kuin `#tool-rail .lt-tile.active` (r. 259) ja
         niillä on SAMA spesifisyys (0,1,2,0) → aktiivitilan tausta katosi hiljaa ja
         aktiivisuudesta jäi näkyviin vain tekstin väri.
     SÄÄNTÖ NYT: täytetty = aktiivinen, aina. Kolme erottuvaa tilaa:
       lepo (ei täyttöä) < hover (himmeä täyttö) < aktiivinen (aksentti + valkoinen).
     ⚠ Aktiivisääntö asettaa taustan JA värin yhdessä (kontrastiansa, ks. dark-auditti). */
  #tool-rail .lt-tile.lt-group { background: transparent; border-color: rgba(219,229,240,0.20); }
  #tool-rail .lt-tile.lt-group:hover { background: rgba(255,255,255,0.10); border-color: rgba(219,229,240,0.35); }
  #tool-rail .lt-tile.lt-group.active,
  #tool-rail .lt-tile.lt-group.lt-open,
  #tool-rail .lt-tile.lt-group[aria-pressed="true"] { background: #1b2c47; border-color: #DBE5F0; color: #fff; }
  #tool-rail .lt-rail-sep { display: flex; flex-direction: column; align-items: center; gap: 2px; margin: 3px 0 1px; width: 52px; user-select: none; }
  #tool-rail .lt-rail-sep i { width: 30px; height: 1px; background: rgba(199,210,226,0.16); display: block; }
  #tool-rail .lt-rail-sep span { font-size: 7px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: #6f86a8; line-height: 1; }
  #tool-rail .lt-tile.lt-helper { color: #93a6c2; }
  #tool-rail .lt-tile.lt-helper svg { width: 18px; height: 18px; }
  /* 2026-06-05: Näkymäkontrollit vasemmassa paneelissa (#view-bar) — oli kelluva #canvas-topbar keskellä piirustusta */
  #view-bar { display: flex; align-items: center; gap: 6px; padding: 7px 8px; border-bottom: 1px solid var(--border); background: var(--panel); flex-shrink: 0; }
  /* 2026-06-05: Näkymäkontrollit OHUENA YLÄPALKKINA piirustusalueen ylälaidassa (center-col) — ei peitä piirustusta */
  #canvas-viewbar { display: flex; align-items: center; gap: 8px; padding: 6px 12px; border-bottom: 1px solid var(--border); background: var(--panel); flex-shrink: 0; }
  /* 2026-06-05: kompaktit IKONI-toggle-napit (oli leveät kytkimet + tekstit → veivät liikaa tilaa) */
  #canvas-viewbar .vb-btn { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 34px; height: 30px; padding: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--text); cursor: pointer; font-family: inherit; }
  #canvas-viewbar .vb-btn svg { width: 17px; height: 17px; stroke: currentColor; }
  #canvas-viewbar .vb-btn:hover { border-color: var(--blue); }
  #canvas-viewbar .vb-btn[aria-pressed="true"] { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  /* 2026-06-28: Ohjeet (?) -napin tila SELVÄSTI näkyväksi — käyttäjä ei tiennyt onko päällä.
     PÄÄLLÄ = täysi aksenttitäyttö + valkoinen ?-ikoni; POIS = himmennetty. Toimii molemmissa teemoissa. */
  #canvas-viewbar #tooltips-btn[aria-pressed="true"] { background: var(--canvas-accent, #1565C0) !important; border-color: var(--canvas-accent, #1565C0) !important; color: #fff !important; }
  #canvas-viewbar #tooltips-btn[aria-pressed="true"] svg { stroke: #fff !important; }
  #canvas-viewbar #tooltips-btn[aria-pressed="false"] { opacity: 0.55; }
  /* 2026-06-05: .vb-btn .hbg-switch -kytkintyylit poistettu — yläpalkin napit ovat nyt ikoneita */
  /* 2026-06-05: ohut erotin ryhmittää "Piilota tausta + Piilota tekstit" -parin erilleen Ohjeet/Näkymä:stä */
  #canvas-viewbar .vb-sep { flex: 0 0 auto; width: 1px; height: 22px; background: var(--border); margin: 0 4px; }
  /* Työkalukohtainen ohjepaneeli (Ohjeet-kytkin päällä → hover työkalun päällä). Selkeä hierarkia: otsikko › kuvaus › listaus › pikanäppäimet › vinkki */
  #tool-help-panel { position: fixed; z-index: 300; width: 300px; padding: 15px 17px; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 14px 36px rgba(20,30,45,.20); font-family: inherit; pointer-events: none; }
  #tool-help-panel .thp-title { font-size: 15px; font-weight: 800; color: var(--text); margin: 0 0 5px; letter-spacing: -0.01em; }
  #tool-help-panel .thp-desc { font-size: 12.5px; line-height: 1.5; color: var(--text); margin: 0 0 10px; }
  #tool-help-panel .thp-bullets { margin: 0 0 4px; padding-left: 17px; }
  #tool-help-panel .thp-bullets li { font-size: 12px; line-height: 1.5; color: var(--text); margin-bottom: 4px; }
  #tool-help-panel .thp-sec { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); margin: 12px 0 6px; }
  #tool-help-panel .thp-keys > div { font-size: 12px; color: var(--text); margin-bottom: 5px; display: flex; align-items: center; gap: 8px; }
  #tool-help-panel kbd { display: inline-block; min-width: 15px; text-align: center; padding: 1px 6px; font-size: 10.5px; font-family: 'JetBrains Mono', ui-monospace, monospace; background: var(--bg); border: 1px solid var(--border); border-radius: 4px; color: var(--text); flex-shrink: 0; }
  #tool-help-panel .thp-tip { margin-top: 12px; padding: 9px 11px; background: #eef3fb; border: 1px solid #fed7aa; border-radius: 8px; font-size: 11.5px; line-height: 1.45; color: #7c2d12; }
  /* 2026-06-05: Yleinen TEEMATTU työkaluvihje — korvaa rumat natiivit title-tooltipit kaikkialla.
     Sama vaalea kortti-perhe kuin #tool-help-panel. Näkyy vain kun Ohjeet-kytkin on päällä. */
  #ui-tip { position: fixed; z-index: 1200; max-width: 280px; padding: 8px 11px; background: var(--panel); border: 1px solid var(--border); border-radius: 9px; box-shadow: 0 10px 30px rgba(20,30,45,.18); font-family: inherit; font-size: 12px; font-weight: 500; line-height: 1.45; color: var(--text); pointer-events: none; opacity: 0; transform: translateY(2px); transition: opacity .12s ease, transform .12s ease; }
  #ui-tip.show { opacity: 1; transform: translateY(0); }
  #view-bar .hdr-menu { flex: 0 0 auto; }
  #view-bar .hdr-menu-btn { height: 30px; }
  /* Tuoterivin JA listan ylätunnisteen pikkuikonit (silmä=peitä, kattavuus) — sama tyyli molemmissa */
  .prod-rowicon { background: transparent; border: 0; cursor: pointer; color: var(--text-muted); padding: 2px; margin-left: 2px; display: inline-flex; align-items: center; justify-content: center; border-radius: 5px; flex-shrink: 0; opacity: .65; transition: opacity .12s, color .12s, background .12s; }
  .prod-rowicon svg { width: 15px; height: 15px; }
  .prod-rowicon:hover { opacity: 1; color: var(--blue); background: rgba(15,158,213,0.10); }
  .prod-rowicon.active { opacity: 1; color: var(--blue); }
  /* Tuotenimen inline-muokkaus: kynänappi nimen vieressä (näkyy kortin hoverilla) + muokkauskenttä */
  .prod-rename-btn { background: transparent; border: 0; cursor: pointer; color: var(--text-muted); padding: 1px; margin-left: 3px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; flex-shrink: 0; opacity: 0; transition: opacity .12s, color .12s, background .12s; }
  .prod-rename-btn svg { width: 13px; height: 13px; }
  .product-card:hover .prod-rename-btn { opacity: .55; }
  .prod-rename-btn:hover { opacity: 1; color: var(--blue); background: rgba(15,158,213,0.10); }
  .product-name-input { flex: 1 1 auto; min-width: 0; font-weight: 600; font-size: 11px; padding: 1px 5px; border: 1px solid var(--blue); border-radius: 4px; background: #fff; color: var(--text); outline: none; font-family: inherit; }
  /* Optimistinen nimenvaihto (2026-08-03): hienovarainen "tallentuu" -merkki.
     Nimi on jo vaihtunut ruudulla; tämä kertoo että kestävä tallennus on vielä
     matkalla. EI estä mitään toimintoa eikä varaa tilaa riviltä. */
  .prod-rename-pending { display: inline-block; vertical-align: middle; flex: 0 0 auto; width: 6px; height: 6px; margin-left: 5px; border-radius: 50%; background: var(--blue); opacity: .85; animation: vek-rename-pulse 1.1s ease-in-out infinite; }
  @keyframes vek-rename-pulse { 0%, 100% { opacity: .25; transform: scale(.8); } 50% { opacity: .95; transform: scale(1); } }
  @media (prefers-reduced-motion: reduce) { .prod-rename-pending { animation: none; opacity: .8; } }
  /* Master-rivi (KAIKKI tuotteet): pikkuikonit kohdistettu tuotteiden silmä/kattavuus-sarakkeiden ylle */
  #product-list-header { display: flex; align-items: center; gap: 5px; padding: 5px 6px; border-bottom: 1px solid var(--border); background: var(--panel); }
  #product-list-header .plh-grow { flex: 1 1 auto; min-width: 0; }
  /* 2026-06-27 (käytettävyys): "Kaikki"-sarakeotsikon luettavuus 9→10,5px + hieman tummempi sävy
     → bulk-toggle-ikonit (kohdistettu silmä/kattavuus-sarakkeiden ylle) hahmottuvat selvemmin. */
  #product-list-header .plh-label { font-size: 10.5px; font-weight: 700; color: var(--text-soft); text-transform: uppercase; letter-spacing: .04em; }
  #product-list-header .plh-delgap { width: 2px; flex: 0 0 auto; }
  #product-list-header .prod-rowicon { opacity: .9; }
  #product-list-header .prod-rowicon.active { background: #eef3fb; }
  /* Näkymä-valikko ohuessa yläpalkissa (#canvas-viewbar) */
  #canvas-viewbar .hdr-menu-btn { height: 30px; padding: 0 8px; gap: 4px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--text); }
  #canvas-viewbar .hdr-menu-btn svg { width: 17px; height: 17px; }
  #canvas-viewbar .hdr-menu-btn:hover { border-color: var(--blue); }
  #canvas-viewbar #view-menu-panel { left: 0; right: auto; }
  /* 2026-06-06: Tasot-nappi siirretty Näkymä-valikosta #canvas-viewbariin (piilota tausta/teksti viereen), IKONI-nappi (vb-btn = sama 34px tyyli kuin hide-bg/text) */
  #canvas-viewbar #layer-btn { display: inline-flex; align-items: center; }
  #canvas-viewbar #layer-toggle-btn { position: relative; }
  #canvas-viewbar #layer-toggle-btn.has-layers { border-color: var(--blue); color: var(--blue); background: #eef3fb; }
  #canvas-viewbar #layer-toggle-btn .layer-count-badge { position: absolute; top: -5px; right: -5px; min-width: 14px; height: 14px; padding: 0 3px; box-sizing: border-box; border-radius: 7px; background: var(--blue); color: var(--gf-on-accent, #fff); font-size: 9px; font-weight: 700; line-height: 14px; text-align: center; pointer-events: none; }
  #view-menu-panel #scale-indicator:hover { color: var(--blue); }
  #project-menu-panel #project-actions { display: flex; flex-direction: column; gap: 2px; }
  #project-menu-panel .project-btn { width: 100%; justify-content: flex-start; }
  /* 2026-06-05: projektipalkin ikoninapit (Hub-paluu + nimen kynä) + nimen inline-muokkaus */
  #project-bar .pb-icon-btn { display:inline-flex; align-items:center; justify-content:center; width:28px; height:28px; padding:0; border:1px solid transparent; border-radius:6px; background:transparent; color:var(--text-muted); cursor:pointer; flex:0 0 auto; transition:background .12s,color .12s,border-color .12s; }
  #project-bar .pb-icon-btn:hover { background:rgba(15,31,58,0.08); color:var(--text); border-color:var(--border); }
  #project-bar #project-rename-btn { opacity:0; }
  #project-bar:hover #project-rename-btn { opacity:1; }
  #project-bar #project-menu { margin-left:2px; }
  #project-bar-name-input { font-size:12px; font-weight:600; border:1px solid var(--blue); border-radius:5px; padding:2px 6px; font-family:inherit; max-width:200px; outline:none; color:var(--text); }
  /* 2026-06-05: yhdenmukaiset valikkorivit — kirjasto/rekisteri-napit samannäköisiksi kuin projektitoiminnot (haamurivit, ei korttireunoja) */
  #project-menu-panel .hdr-icon-btn, #project-menu-panel .rb-btn { background:transparent; border:1px solid transparent; height:28px; padding:0 10px; border-radius:var(--radius-md); font-size:11px; font-weight:600; color:var(--text-muted); }
  #project-menu-panel .hdr-icon-btn:hover, #project-menu-panel .rb-btn:hover { background:#fffaf2; border-color:var(--blue); color:var(--blue); }
  #project-menu-panel .hdr-icon-btn svg { margin-right:5px; }
  #project-menu-panel .vm-row { padding:0; }
  #project-menu-panel .vm-section { padding:8px 8px 3px; }
  #project-menu-panel .danger { background:transparent; border:1px solid transparent; color:#c0392b; height:28px; padding:0 10px; font-size:11px; font-weight:600; justify-content:flex-start !important; border-radius:var(--radius-md); }
  #project-menu-panel .danger:hover { background:#fdecea; border-color:#c0392b; }
  #hdr-left #status { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--text-muted); margin-left: 4px; }
  #project-actions { display: flex; align-items: center; gap: 4px; }
  /* Työkalujen alaryhmät kuvateksteillä (Navigointi · Mittaus & alueet · Merkinnät · Korjaus) */
  .tool-cluster { display: flex; align-items: stretch; }
  .tc-div { width: 1px; background: var(--border); margin: 5px 7px; align-self: stretch; flex-shrink: 0; }
  .tc-body { display: flex; flex-direction: column; align-items: center; gap: 1px; }
  .tc-row { display: flex; align-items: center; gap: 2px; }
  .tc-cap { font-size: 8.5px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: 700; white-space: nowrap; line-height: 1; padding-bottom: 1px; }
  /* Yläpalkin pudotusvalikot (Näkymä ▾ · Kirjasto ▾) */
  .hdr-menu { position: relative; display: inline-flex; }
  .hdr-menu-btn { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; cursor: pointer; font-family: inherit; font-size: 12px; font-weight: 600; color: var(--text); white-space: nowrap; transition: background .12s, border-color .12s, color .12s, transform var(--dur-press) var(--ease-out); }
  .hdr-menu-btn:hover { background: #fffaf2; border-color: var(--blue); color: var(--blue); }
  .hdr-menu-btn.active { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  .hdr-menu-btn svg { width: 15px; height: 15px; stroke: currentColor; flex-shrink: 0; }
  .hdr-menu-btn .hm-caret { font-size: 10px; color: var(--text-muted); }
  .hdr-menu-panel { position: absolute; top: 100%; right: 0; margin-top: 6px; background: var(--panel); border: 1px solid #DDE3EC; border-radius: 10px; box-shadow: 0 8px 24px rgba(15,31,58,.14); padding: 6px; min-width: 248px; z-index: 250; display: none; }
  .hdr-menu-panel.open { display: block; }
  .vm-section { font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); font-weight: 700; padding: 7px 8px 3px; }
  .vm-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 4px 6px; border-radius: 7px; }
  .vm-row > .vm-label { font-size: 12px; color: var(--text); font-weight: 600; white-space: nowrap; }
  .hdr-menu-panel .rb-field { gap: 7px; font-size: 12px; }
  /* Valikon sisällä napit täysleveiksi, vasen-tasaus, menu-tyyli */
  .hdr-menu-panel .rb-btn, .hdr-menu-panel .hdr-icon-btn { width: 100%; justify-content: flex-start; height: 32px; padding: 0 9px; text-transform: none; letter-spacing: 0; font-family: inherit; font-size: 12px; font-weight: 600; background: var(--panel); border: 1px solid var(--border); border-radius: 7px; color: var(--text); }
  .hdr-menu-panel .rb-btn:hover, .hdr-menu-panel .hdr-icon-btn:hover { background: #fffaf2; border-color: var(--blue); color: var(--blue); }
  .hdr-menu-panel .rb-btn[aria-pressed="true"] { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  .hdr-menu-panel .hdr-icon-btn svg { margin-right: 7px; }
  /* Ominaisuus-hallintapaneeli (admin — vain Täysi-taso / Ctrl+Shift+F) */
  #feature-admin-btn { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; cursor: pointer; color: var(--text-muted); flex-shrink: 0; }
  #feature-admin-btn:hover { border-color: var(--blue); color: var(--blue); }
  body.tier-basic #feature-admin-btn { display: none; }
  #feature-admin-bg { position: fixed; inset: 0; background: rgba(15,31,58,0.35); z-index: 4000; display: none; align-items: center; justify-content: center; }
  #feature-admin-bg.show { display: flex; }
  #feature-admin { background: var(--panel); border-radius: 14px; box-shadow: 0 24px 70px rgba(15,31,58,0.3); width: 460px; max-width: 94vw; max-height: 88vh; overflow: auto; }
  #feature-admin .fa-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px 10px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--panel); }
  #feature-admin .fa-head h3 { margin: 0; font-size: 15px; font-weight: 700; color: var(--text); }
  #feature-admin .fa-body { padding: 14px 18px 4px; }
  #feature-admin .fa-presets { display: flex; gap: 8px; }
  #feature-admin .fa-preset { flex: 1; padding: 10px; border-radius: 9px; border: 1px solid var(--border); background: var(--btn-sec-bg, #F1F5F9); cursor: pointer; font-size: 12.5px; font-weight: 700; color: var(--text); }
  #feature-admin .fa-preset:hover { border-color: var(--blue); color: var(--blue); }
  #feature-admin .fa-hint { font-size: 11.5px; color: var(--text-muted); margin: 10px 2px 8px; line-height: 1.5; }
  #feature-admin .fa-row { display: flex; align-items: center; justify-content: space-between; padding: 9px 4px; border-top: 1px solid var(--border); }
  #feature-admin .fa-row .fa-label { font-size: 13px; color: var(--text); }
  #feature-admin .fa-foot { padding: 12px 18px 16px; }
  .fa-switch { position: relative; width: 40px; height: 22px; flex-shrink: 0; }
  .fa-switch input { opacity: 0; width: 0; height: 0; }
  .fa-switch .fa-slider { position: absolute; inset: 0; background: #cbd5e1; border-radius: 22px; transition: .15s; cursor: pointer; }
  .fa-switch .fa-slider:before { content: ''; position: absolute; width: 18px; height: 18px; left: 2px; top: 2px; background: var(--panel); border-radius: 50%; transition: .15s; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
  .fa-switch input:checked + .fa-slider { background: var(--blue); }
  .fa-switch input:checked + .fa-slider:before { transform: translateX(18px); }
  /* Logo-blokki (tumma, brändi-ankkuri) */
  .rb-logo {
    display: flex; align-items: center;
    padding: 0 20px;
    background: var(--navy);
    color: var(--blue);
    font-size: 16px; font-weight: 800; letter-spacing: -0.2px;
    flex-shrink: 0;
    border-right: 2px solid rgba(0,0,0,0.25);
    user-select: none;
  }
  /* Ribbon-ryhmä (pystysuora blokki otsikolla) */
  .rb-group {
    display: flex; flex-direction: column; align-items: stretch;
    border-right: 1px solid var(--border);
    flex-shrink: 0;
  }
  .rb-tools {
    display: flex; align-items: center;
    gap: 5px; padding: 5px 12px; flex: 1;
  }
  .rb-label {
    font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--text-muted); text-align: center; font-weight: 700;
    padding: 0 12px 4px; white-space: nowrap;
  }
  /* Pystyerotin ryhmän sisällä */
  .rb-sep { width: 1px; height: 22px; background: var(--border); margin: 0 3px; flex-shrink: 0; }
  /* Tavallinen ribbon-nappi — rb-dt-yhteensopiva (yhtenäinen 2026-05-21) */
  .rb-btn {
    background: var(--bg); border: 1px solid var(--border);
    border-radius: var(--radius-md); height: 28px; padding: 0 10px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--text); cursor: pointer; white-space: nowrap;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .rb-btn:hover {
    background: #F1F5F9; border-color: #CBD5E1;
    transform: translateY(-1px); box-shadow: 0 3px 8px rgba(15,31,58,0.08);
  }
  /* Pieni ikonappi (sivu eteen/taakse) */
  .rb-icon-btn {
    background: transparent; border: 1px solid var(--border);
    border-radius: 3px; padding: 3px 7px;
    font-family: inherit; font-size: 11px;
    color: var(--text); cursor: pointer; line-height: 1;
  }
  .rb-icon-btn:hover { background: var(--bark-light); }
  /* Sivunumerokenttä */
  .rb-page-input {
    width: 40px; text-align: center;
    border: 1px solid var(--border); border-radius: 3px;
    padding: 3px 4px; font-family: inherit; font-size: 12px;
    color: var(--text); background: var(--panel);
  }
  .rb-page-total { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
  /* Label + select -pari — 2026-05-24k CAD-tyyli (kompakti, vaalea, sopii ribbonin
     kanssa pap-btn:n estetiikkaan). */
  .rb-field {
    display: flex; align-items: center; gap: 5px;
    background: var(--panel); border: 1px solid var(--border);
    border-radius: 5px; height: 26px; padding: 0 8px;
    font-family: inherit;
    font-size: 9px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-muted); white-space: nowrap;
    cursor: default;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
  }
  .rb-field:hover { background: #fffaf2; border-color: var(--blue); color: var(--blue); }
  .rb-field select {
    border: 0; background: transparent;
    font-family: inherit;
    font-size: 11px; font-weight: 700; letter-spacing: 0;
    color: var(--text); cursor: pointer; outline: none;
    text-transform: none;
    padding-right: 0;
  }
  .rb-field:hover select { color: var(--blue); }
  /* Päätoimintanappi (Estimaattori) — tumma laventeli */
  .rb-primary-btn {
    background: #0F1F3A; color: #fff;
    border: none; border-radius: 7px;
    height: 34px; padding: 0 16px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
    cursor: pointer; white-space: nowrap;
    transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  }
  .rb-primary-btn:hover { background: #1E293B; box-shadow: 0 4px 12px rgba(15,31,58,0.20); transform: translateY(-1px); }
  /* Tilaviesti (joustava täyttö) */
  #status {
    flex: 1; padding: 0 12px;
    font-size: 11px; color: var(--text-muted);
    display: flex; align-items: center;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  }

  main { display: flex; flex: 1; overflow: hidden; }

  /* ── Viewport ── */
  #viewport-wrap {
    flex: 1;
    overflow: auto;
    background: #444;
    position: relative;
    /* Tähtäin-malli kursorina viewportissa: ohut musta+valkoinen risti, jotta
       käyttäjä näkee tarkasti minne osoittaa (CAD-mainen). Hotspot (16,16) = keskellä. */
    cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'><g fill='none' stroke-linecap='round'><line x1='16' y1='2' x2='16' y2='12' stroke='%23fff' stroke-width='3'/><line x1='16' y1='2' x2='16' y2='12' stroke='%23000' stroke-width='1.2'/><line x1='16' y1='20' x2='16' y2='30' stroke='%23fff' stroke-width='3'/><line x1='16' y1='20' x2='16' y2='30' stroke='%23000' stroke-width='1.2'/><line x1='2' y1='16' x2='12' y2='16' stroke='%23fff' stroke-width='3'/><line x1='2' y1='16' x2='12' y2='16' stroke='%23000' stroke-width='1.2'/><line x1='20' y1='16' x2='30' y2='16' stroke='%23fff' stroke-width='3'/><line x1='20' y1='16' x2='30' y2='16' stroke='%23000' stroke-width='1.2'/><circle cx='16' cy='16' r='5' stroke='%23fff' stroke-width='2'/><circle cx='16' cy='16' r='5' stroke='%23000' stroke-width='0.9'/></g></svg>") 16 16, crosshair;
  }
  #viewport { position: relative; width: max-content; user-select: none; }
  #viewport img { display: block; pointer-events: none; }
  /* 2026-07-02 Viereen asettelu (osatulostukset kankaalle): arkin runko klikin läpäisevä,
     nimilappu interaktiivinen. z-index 2 → arkki piirtyy SVG:n päälle (käyttäjä pitää arkit
     sivun ulkopuolella; snap ohjaa reunat kiinni). Lappu counter-skaalataan vakiokokoon. */
  #sheet-layer { position: absolute; left: 0; top: 0; width: 0; height: 0; overflow: visible; z-index: 2; }
  .adj-sheet { position: absolute; pointer-events: none; }
  /* 2026-07-06 (käyttäjän overlay-palaute): oletuksena mix-blend-mode:multiply →
     arkin VALKOINEN pohja/marginaali on LÄPINÄKYVÄ (kertolasku valkoisella = taustan
     väri), joten siirretty arkki ei peitä alkuperäisen omaa sisältöä — vain sen tummat
     viivat näkyvät päällekkäin. Raahauksen aikainen inline mixBlendMode='multiply'
     nollataan dropissa (''), jolloin tämä CSS-oletus jää voimaan (ennen: '' = normal
     = valkoinen peitti pohjan). Halutessaan käyttäjä himmentää ◐-napilla (opacity). */
  .adj-sheet > img { display: block; background: #fff; mix-blend-mode: multiply; outline: 1px solid rgba(15,31,58,0.35); box-shadow: 0 3px 14px rgba(15,31,58,0.18); }
  .adj-sheet-chip { position: absolute; bottom: 100%; left: 0; margin-bottom: 3px; transform-origin: 0 100%;
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; pointer-events: auto;
    background: #0F1F3A; color: #fff; font-size: 11.5px; font-weight: 600; letter-spacing: -0.01em;
    padding: 4px 8px; border-radius: 7px; box-shadow: 0 3px 10px rgba(0,0,0,0.25); cursor: grab; user-select: none; }
  .adj-sheet-chip.dragging { cursor: grabbing; }
  /* 2026-07-05 (b): fokusrengas kun lappu on valittu nuolihienosäätöä varten (näppäimistö). */
  .adj-sheet-chip:focus-visible { outline: 2px solid #5EA1FF; outline-offset: 2px; }
  .adj-sheet-chip .asc-scale { color: #9DB4D8; font-weight: 500; }
  /* 2026-07-21 (käyttäjän testipalaute: "epäselvää kummassa kuvassa ne nyt lasketaan").
     Numeromerkintä kuvan reunaan: 1 = laskettava kuva (vihreä = tästä lasketaan),
     2, 3, … = vertailukuvat (sininen = päällekkäisosaa ei lasketa tästä). Värit ovat
     kiinteät eivätkä teematokeneita: nämä lapun sisällä kiinteällä tummalla pohjalla
     piirustuksen päällä, eivät paneelissa. */
  .asc-num { display: inline-flex; align-items: center; justify-content: center;
    min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px;
    background: #2563EB; color: #fff; font-size: 10.5px; font-weight: 800; }
  .active-sheet-badge { position: absolute; left: 0; top: 0; z-index: 3;
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    pointer-events: none; transform-origin: 0 0;
    background: #0F1F3A; color: #fff; font-size: 11.5px; font-weight: 600;
    padding: 4px 8px; border-radius: 7px; box-shadow: 0 3px 10px rgba(0,0,0,0.25); }
  .active-sheet-badge .asc-num { background: #047857; }
  .adj-sheet-chip button { background: rgba(255,255,255,0.12); border: 0; color: #fff; border-radius: 5px;
    font-size: 10.5px; font-weight: 700; padding: 2px 7px; cursor: pointer; line-height: 1.3; font-family: inherit; }
  .adj-sheet-chip button:hover { background: rgba(255,255,255,0.28); }
  /* 2026-07-05 (e) 🎯 KAKSIPISTEKOHDISTUS (overlay v2 #31, app-84.js) ─────────────
     Kaappauskerros: koko viewportin päälle klikkien nappaamiseksi kohdistustilan aikana.
     Läpinäkyvä (arkki + pohja näkyvät läpi) mutta pointer-events:auto → sieppaa klikit.
     z-index arkkien (2) yläpuolelle mutta paneelien alle; risti-kursori. */
  .sheet-tgt-capture { position: absolute; inset: 0; z-index: 30; cursor: crosshair;
    background: rgba(94,161,255,0.04); pointer-events: auto; }
  /* Merkityt kohdistuspisteet (#1/#2). Arkin pisteet siniset, pohjan pisteet oranssit,
     jotta pari erottuu. Keskitetään klikkikohtaan (translate -50%). pointer-events:none
     ettei markkeri estä seuraavaa klikkiä kaappauskerrokseen. */
  .sheet-tgt-marker { position: absolute; z-index: 31; pointer-events: none;
    width: 18px; height: 18px; margin-left: -9px; margin-top: -9px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center; color: #fff;
    font-size: 11px; font-weight: 800; box-shadow: 0 1px 4px rgba(0,0,0,0.4);
    border: 2px solid #fff; }
  .sheet-tgt-marker.tgt-sheet { background: #2563EB; }
  .sheet-tgt-marker.tgt-base { background: #EA7A1E; }
  /* Ohjebanneri (viewportin yläreunaan). data-tone vaihtaa värin (info/warn). */
  .sheet-tgt-banner { position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
    z-index: 32; background: #0F1F3A; color: #fff; font-size: 12.5px; font-weight: 700;
    padding: 7px 14px; border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.3);
    white-space: nowrap; pointer-events: none; }
  .sheet-tgt-banner[data-tone="warn"] { background: #8A4B00; }
  /* 2026-07-05 (g) ⛓ AUTOMAATTISAUMA (overlay v2 #31, app-85.js) ──────────────────
     Sauman overlay-SVG on #sheet-layerin suora lapsi (koordinaatit = aktiivisen sivun
     pt × zoom, kuten arkit). Vinoraita + saumaviiva ovat pointer-events:none paitsi itse
     raahattava viiva (pointer-events:stroke). Chip on foreignObject-HTML jotta luettava. */
  /* z-index: seam-SVG on #sheet-layerin ENSIMMÄINEN lapsi, .adj-sheet sen jälkeen → arkin
     kuva (mix-blend-mode: multiply) maalautuisi kahvojen PÄÄLLE ja tummentaisi ne juuri
     piirustuksen mustan reunakehyksen kohdalla, missä kulmakahvat ovat. Nosto ei riko
     osumia: .adj-sheet on pointer-events:none. */
  .sheet-seam-overlay { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; z-index: 3; }
  .sheet-seam-overlay .seam-line { pointer-events: stroke; }
  /* Päällekkäisyysväritys (käyttäjän linjaus 22.7. lopullinen): VAIN päällekkäisyys merkitään
     PUNAISELLA = jo laskettu toisessa kuvassa → EI lasketa tässä. Loput jää normaaliksi kuvaksi
     (ei valkoista/vaaleaa peitekerrosta). Punaisen läpi näkyy piirustus. */
  .seam-overlap-area { fill: rgba(220,38,38,0.34); stroke: rgba(153,27,27,0.95); }
  /* Bug 1: poissulun (esim. päällekkäisalue) raahattavat kahvat kohdekuvassa. Säde JA
     viivanleveys asetetaan JS:ssä (R_px / uiZoom) → vakiokoko ruudulla; ei stroke-widthia tässä. */
  #draw-overlay .zone-exclude-handle { pointer-events: all; cursor: grab; fill: #fff; stroke: #991B1B; }
  #draw-overlay .zone-exclude-handle:hover { fill: #FEE2E2; }
  /* Reunan keskikahva = "lisää piste" (vaaleampi, ontompi kuin kulmakahva). */
  #draw-overlay .zone-exclude-mid { fill: rgba(255,255,255,0.6); stroke: #DC2626; cursor: copy; }
  /* 2026-07-21 KÄSIN RAJAUS: raahattavat kahvat päällekkäisalueen kulmissa ja reunojen
     keskellä. Säde JA viivanleveys lasketaan JS:ssä (R_px / uiZoom) — vector-effect ei
     kompensoi esivanhemman transform-skaalaa, ks. app-85.js. pointer-events:all tekee
     kahvasta osuttavan vaikka SVG itse on pointer-events:none. */
  .sheet-seam-overlay .seam-handle { pointer-events: all; cursor: grab;
    fill: #FFFFFF; stroke: #B45309; }
  .sheet-seam-overlay .seam-h-mid { fill: #FDE9D2; }
  .sheet-seam-overlay .seam-handle:hover { fill: #FCD9B0; }
  .sheet-seam-overlay .seam-handle.dragging { cursor: grabbing; fill: #B45309; stroke: #FFFFFF; }
  /* Chip-rivi vastaskaalataan JS:ssä (transform: scale(1/uiZoom)) → luettava kaikilla
     zoomeilla, kuten .adj-sheet-chip. Rivi itse on läpinäkyvä kehys chipeille. */
  .seam-chip-row { display: flex; align-items: center; gap: 4px; pointer-events: none; }
  .seam-chip { display: inline-flex; align-items: center; white-space: nowrap; pointer-events: none;
    background: #B45309; color: #fff; font-size: 11px; font-weight: 700; letter-spacing: -0.01em;
    padding: 2px 7px; border-radius: 6px; box-shadow: 0 2px 7px rgba(0,0,0,0.28); font-family: inherit; }
  /* Löydettävyysvihje: kertoo että aluetta voi raahata. Vaaleampi kuin päächip → ei kilpaile. */
  .seam-chip-hint { background: rgba(180,83,9,0.82); font-weight: 600; }
  /* Palautusnappi (↺): näkyy vain kun alue on rajattu käsin. */
  .seam-reset { pointer-events: auto; cursor: pointer; border: 0; font-size: 13px; line-height: 1;
    padding: 3px 8px; background: #0F1F3A; }
  .seam-reset:hover { background: #1E3A6E; }
  /* 2026-07-05 (h) Dedup-vahdin varoitus-chip: erottuva punainen (auditointi, ei muuta määriä).
     pointer-events:auto jotta title-tooltip näkyy hoverilla (chip itsessään ei blokkaa saumaa). */
  .seam-chip-dup { background: #B91C1C; pointer-events: auto; cursor: help; }
  /* Muokkaustavan kytkin on vasemman railin Laske-alapalkissa (#lt-subbar-laske);
     erotin sen ja ydintyökalujen väliin. (2026-07-25: lasso-tilan oma risti-kursori
     poistui lasson mukana — kankaalla on jo oma CAD-tähtäin #viewport-wrapissa.) */
  .lt-subbar .lt-sub-divider { height: 1px; margin: 5px 4px; background: var(--border); }
  /* Tason-vaihdon loading-indikaattori — kuva himmennetään + sykkivä reuna */
  #viewport img.layer-loading {
    opacity: 0.5; filter: blur(1px);
    transition: opacity 0.15s, filter 0.15s;
    outline: 3px solid var(--blue);
    outline-offset: -3px;
    animation: layer-pulse 1.4s ease-in-out infinite;
  }
  @keyframes layer-pulse {
    0%, 100% { outline-color: var(--blue); }
    50% { outline-color: rgba(15,31,58,0.3); }
  }
  #bbox-svg { position: absolute; top: 0; left: 0; pointer-events: none; }
  /* 2026-06-28: manuaalimerkit (📍 Manuaali-työkalu) ovat #bbox-svg:n sisällä, joka on
     pointer-events:none → merkkien klikki (Shift=poista / klik=popup) ei laukennut → "ei voi poistaa".
     Palautetaan pointer-events VAIN merkkikerrokselle; pyöreät napit kaappaavat klikit, välit menevät läpi. */
  #bbox-svg #manual-markers-layer { pointer-events: auto; }
  #bbox-svg #manual-markers-layer text { pointer-events: none; }

  /* ── Right panel ── */
  aside {
    width: 300px;
    background: var(--panel);
    border-left: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    flex-shrink: 0;
    position: relative;
  }
  /* Resize-kahva paneeli vasemmalla reunalla */
  .aside-resize-handle {
    position: absolute;
    left: -3px;
    top: 0;
    bottom: 0;
    width: 6px;
    cursor: ew-resize;
    background: transparent;
    z-index: 50;
    transition: background 0.15s;
  }
  .aside-resize-handle:hover,
  body.aside-resizing .aside-resize-handle {
    background: var(--blue);
    opacity: 0.5;
  }
  body.aside-resizing { cursor: ew-resize !important; user-select: none; }
  body.aside-resizing * { user-select: none; }
  /* 2026-05-30: lisätty flex-wrap — tuotelistan otsikkorivissä 4 napia +
     "+ Uusi (C)" vaativat 357px mutta aside-default 300px → napit
     (etenkin +Uusi, Kattavuus) valuivat ulos oikealta. Wrap nostaa napit
     2. riville kun ei mahdu; leveämmässä asidessa pysyy 1-rivisenä.
     File-panel (Tiedostot+) mahtuu aina → ei vaikutusta sinne. */
  .panel-header {
    padding: 8px 10px;
    border-bottom: 1px solid var(--border);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
  }
  .panel-header h2 {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #999;
    margin: 0;
    flex: 1;
  }
  .panel-header button {
    padding: 3px 9px;
    border: 1px solid var(--border);
    background: var(--panel);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: 12px;
    color: var(--text);
  }
  .panel-header button:hover { background: #f0f8ff; border-color: var(--blue); }

  /* Product list scroll area */
  #product-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 6px;
    min-height: 80px;
  }
  /* Alaosa (Tulokset + Alueet + Admin) — venytettävän kahvan takana */
  .aside-bottom {
    flex-shrink: 0;
    overflow-y: auto;
    border-top: 1px solid var(--border);
    min-height: 60px;
    max-height: 70%;
  }
  /* Vaakasuora drag-kahva product-scroll ja aside-bottom väliin */
  .aside-vsplit-handle {
    height: 6px;
    cursor: ns-resize;
    background: transparent;
    flex-shrink: 0;
    transition: background 0.15s;
    position: relative;
    z-index: 5;
  }
  .aside-vsplit-handle:hover,
  body.aside-vresizing .aside-vsplit-handle {
    background: var(--blue);
    opacity: 0.5;
  }
  body.aside-vresizing { cursor: ns-resize !important; user-select: none; }
  body.aside-vresizing * { user-select: none; }

  /* Yhteinen ✏️-muokkausnappula joka näkyy hover:lla. Klikkaus = avaa modaali.
     Käytä paikoissa joissa muokkaus on vaarallista tehdä vahingossa. */
  .edit-overlay-wrap { position: relative; display: inline-block; }
  .edit-overlay-btn {
    position: absolute; top: 2px; right: 2px;
    width: 22px; height: 22px;
    border-radius: 50%; background: rgba(255,255,255,0.96);
    display: none; align-items: center; justify-content: center;
    cursor: pointer; font-size: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
    border: 1px solid var(--border);
    z-index: 5;
    line-height: 1;
    padding: 0;
  }
  .edit-overlay-wrap:hover .edit-overlay-btn { display: flex; }
  .edit-overlay-btn:hover { background: var(--blue); color: #fff; border-color: var(--blue); }

  /* New product input */
#bbox-svg #direct-preview-layer { pointer-events: none; }
#direct-preview-layer .direct-preview-boxes {
  fill: rgba(20, 132, 94, 0.10);
  stroke: #14845e;
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
/* 2026-07-25: osumien VIIVAT värjätään (Countfire-pariteetti) — bbox jää fallbackiksi.
   V1 (2026-08-01): väri tulee tuotteen TULEVASTA väristä (--dp-color/--dp-fill,
   asetetaan istunnon avauksessa app-20:ssä) — kovakoodattu vihreä jäi ristiin
   tallennuksen jälkeisen tuotevärin kanssa. Fallback = entinen vihreä. */
#direct-preview-layer .direct-preview-vec {
  fill: none;
  stroke: var(--dp-color, #14845e);
  stroke-width: 2.4;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
#direct-preview-layer .direct-preview-vec-fill {
  /* 2026-08-01 käyttäjäpalaute "täysvärjäys kuten lopullisessa": sama semantiikka
     kuin renderMatchesin fillGroups-poluilla (app-60) — TÄYSI täyttö tuotteen
     värillä + evenodd (itseään leikkaava polku / reiät täyttyvät oikein). */
  fill: var(--dp-color, #16a05d);
  fill-rule: evenodd;
  stroke: var(--dp-color, #16a05d);
  stroke-width: 2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
#direct-preview-layer .direct-preview-text {
  /* Sama tyyli kuin lopullisessa (app-60): värillinen kirjain + valkoinen halo. */
  fill: var(--dp-color, #16a05d);
  stroke: #fff;
  paint-order: stroke;
  font-family: sans-serif;
  font-weight: 700;
  pointer-events: none;
}
#direct-preview-layer.is-stale path,
#direct-preview-layer.is-stale text { opacity: 0.38; }
/* Pieni viivamuokkain paneelissa (2026-07-25 ilta): ison modaalin AIDOT elimet
   (#modal-toolrow + #modal-body) telakoituvat #direct-editor-slotiin istunnon
   ajaksi → työkalut/värit/tyylit ovat samat kuin isossa modaalissa; tässä vain
   sovitetaan ne paneelin kokoon (käyttäjä: "modaali ei saa isontua, painikkeet
   voi olla pienemmät"). */
/* 2026-07-28: slotti on paneelin AINOA kasvaja (kiinteä korkeus, ks. paneelin
   sääntölohko) → statusrivien ilmestyminen kutistaa editoria, ei liikuta nappeja.
   min-height: 0 on pakollinen — ilman sitä flex-lapsi ei kutistu sisältönsä alle. */
#direct-editor-slot {
  margin: 8px 0 2px;
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  display: flex;
  flex-direction: column;
}
/* 2026-08-01: toolrow ei ole enää slotin sisällä vaan paneelin suora lapsi
   (slotti leikkasi sen bannerin+nimikentän kasvaessa) → scope paneeliin. */
#direct-signature-panel #modal-toolrow {
  padding: 6px 0 0;
  border-top: none;
  background: transparent;
  gap: 4px;
}
#direct-signature-panel #modal-toolrow button {
  font-size: 11px;
  padding: 3px 7px;
  min-height: 24px;
}
#direct-signature-panel .modal-zoom-ctl b { min-width: 34px; font-size: 10px; }
#direct-editor-slot #modal-body {
  /* Ent. kiinteä 170 px. Nyt editori JOUSTAA slotin mukana: se on se pinta joka
     imee statusrivien tulon/lähdön, jotta nimirivi, Tallenna ja toimintorivi
     pysyvät paikallaan. Lattia estää romahduksen matalalla ikkunalla. */
  flex: 1 1 auto;
  min-height: 150px;
  padding: 8px;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 8px;
}
#direct-editor-slot #modal-svg-wrap {
  width: 100%;
  height: 100%;
  padding: 4px;
  overflow: hidden;
}
#direct-editor-slot #modal-svg {
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
}
/* Lisätunnisteen esikatselu paneelin ULKOPUOLELLE (vasemmalle viereen) —
   pieni editori jäisi muuten kokonaan sen alle (käyttäjäpalaute 25.7. ilta).
   position:fixed ankkuroituu viewporttiin eikä leikkaudu #modal-bodyn
   overflow:hideniin; oikea reuna = paneelin vasen reuna + 8 px rako. */
#direct-editor-slot #modal-float-panel {
  position: fixed;
  top: auto;
  right: calc(12px + min(360px, 100vw - 24px) + 8px);
  bottom: 96px;
  z-index: 451;
}
/* 2026-07-25 käyttäjäpalaute "kun zoomaa niin se katoaa, se pitää olla kiinteä":
   pieni modaali on KIINTEÄ ruudulla (fixed) — ei seuraa kanvaasin zoomia/scrollia.
   Oikea alakulma zoom-kontrollien yläpuolella, poissa piirustuksen päältä. */
#direct-signature-panel {
  position: fixed;
  /* 2026-08-01 käyttäjäpalaute: paneeli aukeaa VASEMMALLE (piirustuksen
     symbolit ovat useimmiten keskellä/oikealla → paneeli ei peitä niitä)
     ja on raahattavissa otsikostaan (app-20 _directPanelDragWiring;
     siirretty sijainti muistetaan localStoragessa). */
  left: 12px;
  right: auto;
  bottom: 96px;
  z-index: 450;
  width: min(360px, calc(100vw - 24px));
  /* 2026-07-28 KRIITTINEN (käyttäjä: "se minimodaalin tallenna painike ei tee mitään
     kun on haku tehty … sain painettua kun painoin enteria").
     JUURISYY (selainmitattu, ikkuna 1000 px): paneeli on ALAREUNAAN ankkuroitu
     (bottom: 96px), joten JOKAINEN sisällön kasvu työntää kaikkia kontrolleja YLÖS.
     Kaksi kasvua saapuu asynkronisesti 0,3–2 s kirjoittamisen jälkeen — siis juuri
     kun käyttäjä osoittaa Tallenna-nappia:
       · rekisterihaun tilarivi  0 → 29 px
       · "Ei osumia …" -viesti  18 → 32 px (kietoutuu kahdelle riville)
     Mitattu: painallus osui nappiin (y 556–586), 900 ms myöhemmin nappi oli y 525–555
     ja vapautus samassa pisteessä osui DIV:iin → selain EI muodosta click-tapahtumaa
     lainkaan (btnClicks=0). Enter toimi, koska näppäinpolku ei tee osumatestiä.
     KORJAUS: korkeus on KIINTEÄ ja sisällön muutokset imeytyvät editorislottiin
     (ainoa flex-kasvaja) → yksikään kontrolli ei liiku. ⛔ Älä palauta pelkkää
     max-heightia: se sallii juuri sen kasvun joka siirtää napin pois kursorin alta. */
  height: min(450px, calc(100vh - 116px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--panel);
  box-shadow: 0 12px 34px rgba(15, 23, 42, 0.28);
}
#direct-signature-panel[hidden], #direct-signature-panel [hidden] { display: none; }
/* 2026-08-01: piilotettujen viivojen vihje rajauksessa. */
#direct-hidden-notice {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 4px 0 2px; padding: 5px 8px; font-size: 11px; line-height: 1.4;
  color: var(--text-soft); background: var(--bark-light, #F5F2EB);
  border: 1px solid var(--border); border-radius: 7px;
}
#direct-hidden-notice button {
  padding: 3px 8px; font-size: 11px; font-weight: 600;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--btn-bg); color: var(--btn-fg);
}
/* 2026-08-01: pikanäppäinvihjeet — hillitty yksirivinen (rivittyvä) lista. */
#direct-kbd-hints {
  display: flex; flex-wrap: wrap; gap: 4px 10px;
  padding: 5px 2px 0; font-size: 10px; color: var(--text-soft);
}
#direct-kbd-hints kbd {
  font: 600 9.5px ui-monospace, monospace; background: var(--bark-light, #F5F2EB);
  border: 1px solid var(--border); border-radius: 4px; padding: 0 4px;
}
/* 2026-08-01 ikkunamanageri: kaikkien modaalien koon raahauskahva. */
.vk-resize-grip {
  position: absolute; right: 2px; bottom: 2px; width: 16px; height: 16px;
  cursor: nwse-resize; z-index: 5;
  background:
    linear-gradient(135deg, transparent 0 50%, var(--text-muted) 50% 56%,
      transparent 56% 66%, var(--text-muted) 66% 72%, transparent 72% 82%,
      var(--text-muted) 82% 88%, transparent 88%);
}
/* 2026-08-01: reunaliukupaneelin (cluster-panel, layer-popover) leveyskahva —
   pystyraita vasemmassa reunassa. Paneelin auki/kiinni-tila on transform,
   joten vain leveyttä säädetään (app-90 makeDockResizable). */
.vk-dock-wgrip {
  position: absolute; left: 0; top: 0; bottom: 0; width: 7px;
  cursor: ew-resize; z-index: 6;
}
.vk-dock-wgrip:hover { background: color-mix(in srgb, var(--text-muted) 25%, transparent); }
/* Ketjupalkin koonmuutos: inline-korkeus (raahattu koko) → sisältö skrollaa
   leikkautumisen sijaan. */
#chain-bar.visible[style*="height:"] { display: flex; flex-direction: column; }
#chain-bar.visible[style*="height:"] #cb-list { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* 2026-08-01: koon raahauskahva (oikea alakulma). */
#direct-panel-resize {
  position: absolute; right: 2px; bottom: 2px; width: 16px; height: 16px;
  background:
    linear-gradient(135deg, transparent 0 50%, var(--text-muted) 50% 56%,
      transparent 56% 66%, var(--text-muted) 66% 72%, transparent 72% 82%,
      var(--text-muted) 82% 88%, transparent 88%);
}
#viewport-wrap #direct-signature-panel #direct-panel-resize { cursor: nwse-resize !important; }
/* Kiinteän korkeuden kumppani: vain editorislotti joustaa, muut lohkot pitävät
   mittansa → statusrivin ilmestyminen kutistaa editoria eikä liikuta nappeja. */
/* :not(#…) nostaa tarkkuuden yli slotin oman säännön → järjestys tiedostossa ei
   voi vahingossa kumota kasvajaa (kaksi paljasta id-sääntöä olisivat tasapelissä). */
#direct-signature-panel > *:not(#direct-editor-slot) { flex: 0 0 auto; }
#direct-signature-panel h3 { margin: 0 0 8px; font-size: 14px; user-select: none; }
/* Raahauskahvan kursori: sama spesifisyys+!important-malli kuin paneelin muissa
   kursorisäännöissä — työkalutilat (pan/layer-pick/…) käyttävät
   `#viewport-wrap *`-universaalia !importantilla ja voittaisivat muuten
   (portti: test_direct_panel_cursor). */
#viewport-wrap #direct-signature-panel h3 { cursor: grab !important; }
#viewport-wrap #direct-signature-panel h3:active { cursor: grabbing !important; }
/* Kahden rivin varaus: pisin viesti mitattu 32 px sekä suomeksi että englanniksi
   ("Ei osumia — tarkista rajaus …" / "No matches — check the selection …").
   Ilman varausta tekstin vaihtuminen siirtäisi nimirivin ja Tallenna-napin. */
#direct-preview-status { min-height: 32px; color: var(--text-soft); font-size: 12px; }
/* Nimeäminen + Tallenna SAMASSA ikkunassa (2026-07-27 käyttäjäpalaute "siitä
   samasta voi tehdä kaiken siihen liittyvän"). Kenttä on tuotelistan
   nimeämisrivin peili — app-20.js pitää arvot synkassa molempiin suuntiin. */
.direct-name-row {
  position: relative; display: flex; gap: 6px; align-items: center; margin: 8px 0 2px;
}
.direct-name-row .npi-input { flex: 1 1 auto; min-width: 0; }
#direct-panel-label-status:empty { display: none; }
#direct-panel-label-status { margin: 2px 0 0; }
/* Ehdotuslista pysyy paneelin sisällä (paneeli on itse fixed → ei leikkaudu). */
#direct-panel-autocomplete-list {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 2000;
  max-height: 260px; overflow-y: auto;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18); border-radius: var(--radius-md);
  background: var(--panel);
}
.direct-preview-metrics { display: flex; gap: 14px; margin: 8px 0; font-size: 12px; align-items: center; }
/* Tuotteen väriswatch pienessä ikkunassa (2026-07-26 "sigin värin vaihto") —
   JS pitää taustan synkassa colorForLabel-arvoon (_directSyncCounts). */
.direct-color-swatch {
  width: 20px; height: 20px; flex: 0 0 auto; padding: 0;
  border: 1px solid var(--border); border-radius: 6px;
  background: #14845e;
}
.direct-color-swatch:hover { box-shadow: 0 0 0 2px var(--btn-bg-hover); }
.direct-preview-actions { display: flex; flex-wrap: wrap; gap: 6px; }
#direct-signature-panel .direct-preview-actions button { min-height: 30px; }
/* Nimeämisrivi tuotelistassa (2026-07-25 Countfire-pariteetti) */
/* Button 2026-07-26 alkaen: avaa värivalitsimen (sama polku kuin tuotekortin swatch). */
.direct-naming-row .direct-row-swatch {
  width: 14px; height: 14px; border-radius: 4px; flex: 0 0 auto;
  background: #14845e; border: 1px solid var(--border); padding: 0; cursor: pointer;
}
.direct-naming-row .direct-row-swatch:hover { box-shadow: 0 0 0 2px var(--btn-bg-hover); }
.direct-naming-row #direct-row-count {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 15px; font-weight: 800; flex: 0 0 auto;
}
/* Sama Tallenna-tyyli MOLEMMISSA nimeämispaikoissa (2026-07-27): tuotelistan
   rivillä ja pienen ikkunan nimirivillä — sama toiminto, sama ulkoasu. */
.direct-naming-row .direct-row-save,
.direct-name-row .direct-row-save {
  flex: 0 0 auto; min-height: 30px; padding: 4px 12px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--btn-bg); color: var(--btn-fg); font-weight: 600; font-size: 12px;
}
.direct-naming-row .direct-row-save:hover,
.direct-name-row .direct-row-save:hover { background: var(--btn-bg-hover); }
.direct-naming-row #direct-signature-label-status { margin-top: 6px; }
/* position:fixed kuten C-rivin autocompletella: vuotaa #product-scrollin yli.
   JS päivittää top/left/width rivin rakennuksessa + scroll/resize-tapahtumissa. */
#direct-signature-autocomplete-list {
  position: fixed; z-index: 2000; max-height: 320px; overflow-y: auto;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18); border-radius: var(--radius-md); background: var(--panel);
}
/* 2026-07-25: `body.inline-select-on #viewport-wrap { cursor: crosshair }` POISTETTU.
   Suora valinta on nyt OLETUSTILA, joten sääntö olisi käytännössä aina päällä ja
   korvaisi kankaan oman CAD-tähtäimen (01-base-2.css #viewport-wrap) tavallisella
   järjestelmäristillä — juuri sen jota vastaan tähtäin alun perin tehtiin. */

/* ── Suoran valinnan paneelin KURSORI (2026-07-25 käyttäjäpalaute) ───────────────
   "uuden modaalin painikkeiden painaminen on samalla cursorilla eli sillä isolla
   tähtäimellä kuin viewportissa, se pitää olla erilainen … ettei sekoita sitä
   viewportiin."  JUURISYY: #direct-signature-panel on #viewport-wrapin LAPSI (se on
   fixed, mutta DOM-vanhempi on kangas) → cursor periytyy kankaan tähtäimestä, eikä
   sovelluksessa ole yleistä `button { cursor: pointer }` -sääntöä. !important siksi,
   että työkalutilat (pan/layer-pick/wiring-pick/cad-cross) käyttävät universaalia
   `#viewport-wrap *` + !important -sääntöä joka osuu paneelin nappeihin SUORAAN.
   HUOM: telakoitu editori (#modal-body) asettaa oman `cursor: var(--vec-cursor)`
   -sääntönsä ELEMENTILLE → se voittaa tämän periytyvän arvon ilman eri mainintaa,
   eli valintapinta pitää ison modaalin hiusristikon.
   ⚠ 2026-07-28 KORJAUS (käyttäjä: "painikkeiden paino on sillä samalla
   tähtäinkursorilla"): pelkkä `html body #…panel button` (1 id, 0 luokkaa,
   3 elem) HÄVISI työkalutilojen säännölle `html body.pan-tool #viewport-wrap *`
   (1 id, 1 LUOKKA, 2 elem) — luokkamäärä vertaillaan ennen elementtimäärää.
   Mitattu paneelin päällä: cursor === "none" (cad-cross-on). Nyt selektoreissa
   on TOINEN id (#viewport-wrap) → 2 id:tä voittaa minkä tahansa yhden id:n +
   luokan säännön, myös vielä kirjoittamattomat työkalutilat. Vahti:
   `_perf/test_direct_panel_cursor.py` laskee tarkkuudet ja vertaa. */
html body #viewport-wrap #direct-signature-panel { cursor: default !important; }
html body #viewport-wrap #direct-signature-panel button,
html body #viewport-wrap #direct-signature-panel label,
html body #viewport-wrap #direct-signature-panel select,
html body #viewport-wrap #direct-signature-panel input[type="checkbox"],
html body #viewport-wrap #direct-signature-panel input[type="range"],
html body #viewport-wrap #direct-signature-panel input[type="color"] { cursor: pointer !important; }
html body #viewport-wrap #direct-signature-panel input[type="text"],
html body #viewport-wrap #direct-signature-panel input[type="number"],
html body #viewport-wrap #direct-signature-panel input:not([type]),
html body #viewport-wrap #direct-signature-panel textarea { cursor: text !important; }

/* ── "Näytä osumat" -nappi + korostusrenkaat (2026-07-25) ───────────────────────
   Käyttäjä: "juuri tehdyllä pitää olla jokin indikointi että mistä ne löytyy …
   pitää olla painikkeen takana että voit painaa jos haluat." Renkaat piirretään
   #bbox-svg:hen (sama koordinaatisto kuin matchit: pt × state.zoom); JS kompensoi
   uiZoomin säteessä ja viivanpaksuudessa, jotta rengas pysyy samankokoisena
   RUUDULLA (sama oppi kuin poissulkualueen raahauskahvoissa). Puhtaasti
   visuaalinen — ei kosketa laskentaan eikä tunnistukseen. */
.direct-locate-btn {
  margin-left: 6px; padding: 1px 7px; font-size: 10.5px; font-weight: 600;
  font-family: inherit; line-height: 1.6;
  border: 1px solid var(--border); border-radius: 5px;
  background: var(--btn-sec-bg); color: var(--btn-sec-fg);
}
.direct-locate-btn:hover { background: var(--btn-bg-hover); color: var(--btn-fg); }
.direct-locate-btn[aria-pressed="true"] { background: var(--blue); border-color: var(--blue); color: #fff; }
/* Ulkoasu (käyttäjäpalaute 25.7. "renkaassa pitää olla HALO ja kauniimpi"): KOLME
   kerrosta per osuma, sama kaksisävyperiaate kuin kankaan tähtäimessä ja pohjakuvien
   luonnosviivassa — pelkkä sininen rengas hukkuu tummaan CAD-musteeseen ja vaalea
   rengas valkoiseen pohjaan, halo tekee siitä luettavan kummallakin:
     .dl-pulse — laajeneva "sonar"-sykähdys pohjalla (vetää katseen)
     .dl-halo  — pehmeä valkoinen halo
     .dl-ring  — terävä aksenttirengas päällimmäisenä
   transform-box: fill-box → scale kiertyy renkaan OMAN keskipisteen ympäri
   (ilman sitä origo olisi SVG-juuren nurkka ja sykähdys lentäisi pois paikaltaan). */
#direct-locate-layer { pointer-events: none; }
#direct-locate-layer circle { fill: none; transform-box: fill-box; transform-origin: center; }
/* Halo ja aksenttirengas ovat PYSYVIÄ (ei opacity-animaatiota): sykkivä rengas
   näytti puoliksi haalistuneelta aina kun katse osui siihen väärässä vaiheessa.
   Liike on vain sykähdyksessä, joka vetää katseen ilman että merkintä itse
   heikkenee. */
/* ⚠ VÄRI ON LITERAALI, EI --canvas-accent (mitattu selaimessa 25.7.): vaaleassa
   graphite-teemassa sekä --canvas-accent ETTÄ --blue ovat #1D1D1F eli lähes
   MUSTIA → rengas piirtyi mustana mustan CAD-viivan päälle ja hukkui täysin.
   #1565C0 on VAIN FALLBACK: 2026-07-26 käyttäjäpalaute "halo ja löydetty laite
   sigin omalla värillä" → JS (_directLocateRender) ylikirjoittaa renkaan ja
   sykähdyksen strokeksi tuotteen oman värin inline-tyylillä (voittaa tämän
   luokkasäännön). Valkoinen halo pysyy — se tekee minkä tahansa tuotevärin
   luettavaksi sekä mustalla CAD-musteella että valkoisella pohjalla. */
#direct-locate-layer .dl-halo { stroke: #fff; stroke-opacity: .95; }
#direct-locate-layer .dl-ring { stroke: #1565C0; stroke-linecap: round; }
#direct-locate-layer .dl-pulse {
  stroke: #1565C0;
  animation: direct-locate-sonar 2.2s cubic-bezier(.22, .61, .36, 1) infinite;
}
@keyframes direct-locate-sonar {
  0%   { transform: scale(1);    opacity: .6; }
  70%  { transform: scale(1.8);  opacity: 0; }
  100% { transform: scale(1.8);  opacity: 0; }
}
/* Liikeherkkyys: sykähdys pois, rengas + halo jäävät (indikointi ei katoa). */
@media (prefers-reduced-motion: reduce) {
  #direct-locate-layer .dl-pulse { display: none; }
}

/* ── Jaettu sulkuraksi (2026-07-26 käyttäjäpalaute "kaikissa modaaleissa pitää
   olla myös raksi") ──────────────────────────────────────────────────────────
   Yksi luokka + data-x-for="<peruutusnapin-id>": delegoitu klikki (app-01.js)
   ohjaa popupin OMAAN peruutus-/ohituspolkuun → raksi käyttäytyy TÄSMÄLLEEN
   kuten popupin Esc — ei rinnakkaista sulkulogiikkaa joka voisi ajautua eri
   tilaan. Kontin pitää olla positioned (fixed/absolute/relative). */
.vk-x {
  position: absolute; top: 6px; right: 6px; z-index: 5;
  width: 24px; height: 24px; padding: 0; line-height: 1;
  border: 0; border-radius: 6px; background: transparent;
  color: var(--text-muted); font-size: 16px; font-family: inherit; cursor: pointer;
}
.vk-x:hover { background: var(--btn-sec-bg); color: var(--text); }
/* Nämä modaalit ovat overlay-taustan flex-lapsia ILMAN omaa positiota →
   ilman tätä raksi ankkuroituisi KOKO RUUDUN overlayhin (fixed-tausta). */
#ui-dialog, #draw-start-popup, #hub-new-modal { position: relative; }
/* Navy-otsikkopalkin päällä (esim. mittakaavamodaali) valkoinen raksi. */
.vk-x-onnavy { color: rgba(255,255,255,0.75); }
.vk-x-onnavy:hover { background: rgba(255,255,255,0.14); color: #fff; }
  #new-product-row {
    display: none;
    background: #fff8e8;
    border: 2px solid var(--blue);
    border-radius: var(--radius-md);
    padding: 7px 8px;
    margin-bottom: 6px;
    align-items: center;
    gap: 5px;
  }
  #new-product-row.show { display: flex; }
  #new-product-input {
    flex: 1;
    padding: 5px 8px;
    border: 1px solid var(--blue);
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    min-width: 0;
  }
  #new-product-input:focus { outline: 2px solid var(--blue); }
  .np-btn {
    padding: 5px 9px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: 13px;
    border: 0;
  }
  #new-product-ok { background: var(--blue); color: #fff; }
  #new-product-cancel { background: #eee; color: #555; }

  /* Product card */
  /* 2026-05-12 KÄYTTÄJÄPYYNTÖ: tuotekortit tiiviimmiksi (CountFire-tyyli) — vähemmän
     tilaa per rivi, mutta laajennettu paneeli aktiivisena pysyy ennallaan. */
  .product-card {
    border-left: 3px solid #aaa;
    background: var(--panel);
    border-radius: 0 8px 8px 0;
    margin-bottom: 1px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    overflow: hidden;
  }
  .product-card.active {
    background: #eef3fb;
    box-shadow: 0 0 0 2px var(--blue);
  }
  /* Body-tila: kun aktiivinen tuote odottaa bbox:ia → cursor crosshair viewport:ssa */
  body.awaiting-bbox-add #viewport-wrap,
  body.awaiting-new-product #viewport-wrap { cursor: crosshair; }
  .product-card.new-placeholder { border-left-style: dashed; background: #fffdf5; }
  /* 2026-07-25 flow-katselmus: inkrementaalihaku peruuntui (uusi rajaus syrjäytti
     sen) ja label on uudelleenyritysjonossa. Määrä kortilla on TILAPÄISESTI
     vajaa → merkki on pakko näkyä, muuten väärä luku jää huomaamatta. */
  .product-card.inc-requeued { box-shadow: inset 3px 0 0 #E8A33D; }
  .product-card.inc-requeued .product-meta::after {
    content: "⏳";
    margin-left: 5px;
    font-size: 11px;
    opacity: .85;
  }
  @media (prefers-reduced-motion: reduce) {
    .product-card.inc-requeued { transition: none; }
  }
  /* 2026-05-17: Inline "uusi tuote" -rivi (korvasi #new-product-popup-modaalin).
     C-näppäin / + Uusi avaa input + autocomplete suoraan tuotelistan kärkeen. */
  .product-card.pending-input {
    border: 1px dashed var(--blue);
    background: #f4f8ff; padding: 8px 10px;
    box-shadow: 0 2px 10px rgba(37,99,235,0.12);
    overflow: visible !important;  /* anna autocomplete:n vuotaa kortin ulkopuolelle */
  }
  .product-card.pending-input .npi-input {
    width: 100%; padding: 7px 9px; font-size: 13px; border: 1px solid var(--blue);
    border-radius: 5px; font-family: inherit; outline: 0; background: var(--panel); box-sizing: border-box;
  }
  .product-card.pending-input .npi-input:focus { box-shadow: 0 0 0 2px rgba(37,99,235,0.18); }
  .product-card.pending-input .npi-cancel {
    background: none; border: 0; cursor: pointer; color: var(--text-muted);
    font-size: 18px; padding: 0 6px; line-height: 1; flex-shrink: 0;
  }
  .product-card.pending-input .npi-cancel:hover { color: var(--text); }
  .product-card.pending-input .npi-hint {
    color: var(--text-muted); font-size: 11px; margin-top: 5px; padding-left: 2px;
  }
  /* position:fixed jotta autocomplete vuotaa #product-scroll:n overflow:auto:n yli.
     JS päivittää top/left/width openNewProductRow + scroll/resize-tapahtumissa. */
  #new-product-inline-autocomplete {
    position: fixed; z-index: 2000; max-height: 320px; overflow-y: auto;
    box-shadow: 0 8px 24px rgba(0,0,0,0.18); border-radius: var(--radius-md); background: var(--panel);
  }

  /* Drag & drop: sig tuotteesta toiseen */
  .tgrid-row[draggable="true"] { cursor: grab; }
  .tgrid-row[draggable="true"]:active { cursor: grabbing; }
  .tgrid-row.dragging { opacity: 0.45; }
  .product-card.sig-drop-target {
    box-shadow: 0 0 0 1px rgba(30,47,74,0.18) inset;
  }
  .product-card.sig-drop-over {
    background: rgba(219,229,240,0.55);
    box-shadow: 0 0 0 2px var(--blue) inset;
  }

  .product-header {
    display: flex;
    align-items: center;
    padding: 1px 6px;
    cursor: pointer;
    gap: 4px;
    min-height: 0;
  }
  /* 2026-06-05: tiiviimmät tuoterivit — × ja rivi-ikonit pienemmiksi → matalampi rivi (~24px, oli 32px) */
  .product-header .prod-del { width: 22px; height: 22px; font-size: 15px; }
  .product-header .prod-rowicon { padding: 1px; }
  .product-header .prod-rowicon svg { width: 14px; height: 14px; }
  /* 2026-06-27 (käytettävyys): näkymätön klikkausalueen laajennus 16→~22px ILMAN korkeampaa riviä
     (säilyttää yllä olevan 2026-06-05 tiiviin rivin). Sama tekniikka kuin väriläiskällä (::before). */
  .product-header .prod-rowicon { position: relative; }
  .product-header .prod-rowicon::before { content: ''; position: absolute; inset: -3px; }
  .product-header:hover { background: rgba(0,0,0,0.025); }
  .product-name { flex: 1; font-weight: 600; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* 2026-05-12 vaihe 1: rivi tiiviimmäksi (Elements/Matches-taulukko tulee erilliseen
     alapaneeliin myöhemmissä vaiheissa). */
  .product-meta { font-size: 12px; font-weight: 700; white-space: nowrap; padding: 0 3px; min-width: 22px; text-align: right; font-family: 'JetBrains Mono', ui-monospace, monospace; letter-spacing: -0.02em; }
  .product-meta.has-matches { color: #1e40af; }
  .product-meta.no-matches { color: #cbd5e1; font-weight: 600; }
  /* 2026-05-15: rekisteri-tila-merkki tuotekortissa */
  .prod-rek-badge { display:inline-block; font-size: 11px; line-height: 1; padding: 0 4px; flex-shrink: 0; cursor: help; }
  .prod-rek-ok { color: #22c55e; }     /* vihreä — toimii viennissä */
  .prod-rek-empty { color: #eab308; }  /* keltainen — rekisterissä mutta tuotenrot puuttuvat */
  .prod-rek-none { color: #cbd5e1; }   /* harmaa — ei rekisterissä */
  /* 2026-05-20: text-discriminator badge — näyttää sigin valitut kirjaimet */
  .prod-text-badge {
    display: inline-block;
    font-size: 10px;
    line-height: 1;
    padding: 2px 5px;
    border-radius: var(--radius-lg);
    background: #fef3c7;
    color: #92400e;
    border: 1px solid #f59e0b;
    flex-shrink: 0;
    font-weight: 600;
    cursor: help;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    letter-spacing: 0.02em;
  }
  .prod-text-badge.prod-text-filled {
    background: #f1f5f9;
    color: #475569;
    border-color: #cbd5e1;
    font-family: inherit;
  }
  /* Aktiivisuus-nuoli (▸ inaktiivi → ▾ aktiivi) */
  .product-toggle-arrow {
    display: inline-block; width: 9px; font-size: 9px; line-height: 1;
    color: var(--text-muted); flex-shrink: 0;
    transition: transform 0.15s, color 0.15s;
    text-align: center;
  }
  .product-card.active .product-toggle-arrow { transform: rotate(90deg); color: var(--text); }
  /* A1: ankkurin terveys -piste tuotekortissa.
     2026-05-08 UI-siivous: näytetään AINA vain "poor" (punainen varoitus). Good/ok piilotettu. */
  .health-dot {
    display: inline-block; width: 9px; height: 9px; border-radius: 50%;
    flex-shrink: 0; box-shadow: 0 0 0 1px rgba(255,255,255,0.5), 0 1px 2px rgba(0,0,0,0.15);
  }
  .health-dot.health-poor { background: #ef4444; }
  /* 2026-05-11: Tab-rivi tuotelistalla. Aktiivinen tab korostettu sinisellä alaviivalla. */
  #product-tabs .ptab {
    flex: 1; min-width: 0; padding: 9px 2px 8px; border: 0; background: transparent;
    border-bottom: 2px solid transparent; cursor: pointer;
    font-family: inherit; font-size: 11px; font-weight: 600;
    color: var(--text-muted); display: flex; align-items: center; justify-content: center; gap: 5px;
    transition: color 0.1s, border-color 0.1s, background 0.1s;
  }
  /* 2026-06-11 UX v2 (käyttäjäpalaute: 5 ahdasta 8.5px-nimeä = kömpelö): tabit ikoni+määrä,
     AKTIIVISEN tabin koko nimi + selite näkyy #ptab-title-rivillä tabirivin alla (pysyvä,
     ei pelkkä hover → toimii myös ei-teknisille). Nimet jäävät DOMiin ruudunlukijoille. */
  #product-tabs .ptab .ptab-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  #ptab-title {
    display: flex; align-items: baseline; gap: 5px; padding: 4px 10px 5px;
    font-size: 10.5px; line-height: 1.25; color: var(--text-soft); /* 2026-06-28 AA: --text-muted (#86868B=3.62:1) → --text-soft (6.65:1 vaalea / 7.32:1 tumma) */
    background: var(--panel); border-bottom: 1px solid var(--border);
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
  #ptab-title b { color: var(--text); font-size: 11px; flex: 0 0 auto; }
  #ptab-title span { overflow: hidden; text-overflow: ellipsis; }
  /* 2026-06-28 AA: Chromen UA-placeholder (#757575) jää 4.27:1 vaaleassa / ~3.6:1 tummassa → teema-token --text-soft (6.16/6.62:1). opacity:1 koska Firefox himmentää placeholderia. */
  #product-search::placeholder { color: var(--text-soft); opacity: 1; }
  #product-tabs .ptab:hover { background: rgba(0,0,0,0.03); color: var(--text); }
  #product-tabs .ptab.active {
    color: var(--blue); border-bottom-color: var(--blue); background: var(--panel);
  }
  #product-tabs .ptab .ptab-count {
    font-size: 9.5px; opacity: 0.7; font-family: 'JetBrains Mono', ui-monospace, monospace;
  }
  /* 2026-05-24h: tab-napin SVG-ikoni (Lucide-tyyli) — currentColor → muuttuu aktiivisena */
  #product-tabs .ptab .ptab-ico {
    display: inline-flex; align-items: center; justify-content: center;
    width: 17px; height: 17px;
  }
  #product-tabs .ptab .ptab-ico svg { width: 17px; height: 17px; stroke: currentColor; }
  /* 2026-05-24h: Tuotelistan otsikkonapit (Mallit / Rekisteri / Monivalinta / Kattavuus) */
  .hdr-icon-btn {
    font-size: 11px; padding: 0 10px; border-radius: var(--radius-md); height: 28px;
    border: 1px solid var(--border); background: var(--panel); cursor: pointer;
    color: var(--text); font-weight: 600;
    display: inline-flex; align-items: center; gap: 5px;
    font-family: inherit;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
  }
  .hdr-icon-btn:hover { background: #fffaf2; border-color: var(--blue); color: var(--blue); }
  .hdr-icon-btn.active { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  .hdr-icon-btn svg { stroke: currentColor; flex-shrink: 0; }
  /* 2026-05-24i/j: Ribbon-tyokalupainike — CAD-mainen kompakti tyyli.
     Kayttajapyynto 2026-05-24j: 'Ribbonissa on liian isot tekstit, voi olla
     tuollainen missä on pienemmät symbolit. Teema pitää olla sama kuitenkin.'
     Referenssi: AutoCAD ribbon — pienet tekstit alle, kompakti nappi, ikoni
     suhteessa isohko. Vektoria light theme + oranssi aksentti sailoa. */
  .ribbon-btn {
    flex: 0 0 auto; min-width: 42px; max-width: 60px;
    padding: 3px 4px 3px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 5px;
    cursor: pointer;
    font-family: inherit; font-size: 10px; font-weight: 600;
    color: var(--text-muted);
    text-align: center; line-height: 1.15;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px;
    letter-spacing: 0;
    white-space: nowrap;
  }
  .ribbon-btn:hover {
    background: #fffaf2;
    border-color: var(--blue);
    color: var(--blue);
  }
  .ribbon-btn.active {
    background: #eef3fb;
    border-color: var(--blue);
    color: var(--blue);
  }
  .ribbon-btn svg {
    width: 18px; height: 18px;
    stroke: currentColor;
    stroke-width: 1.8;
    flex-shrink: 0;
    display: block;
  }
  /* Erityistapaukset: Alue (Z) on oranssi koska se on laskennan ydin, Pyyhi on harmaa-aktiivinen */
  .ribbon-btn.is-zone.active { background: var(--blue); border-color: var(--blue); color: #fff; }
  .ribbon-btn.is-erase.active { background: var(--bark-warm, #64748B); border-color: var(--bark-warm, #64748B); color: #fff; }
  /* 2026-06-04: Käsi/PAN-työkalu — navigointi, erottuva sininen aktiivisävy (ei piirtotyökalu) */
  .ribbon-btn.rb-pan.active { background: #e8f4fb; border-color: var(--blue, #0F9ED5); color: var(--blue, #0F9ED5); }
  /* Hand-ikoni on yksityiskohtainen → 18px:ssä haalea. Tummempi perusväri + paksumpi viiva → näkyy selvästi valkealla. */
  .ribbon-btn.rb-pan { color: var(--text); }
  .ribbon-btn.rb-pan svg { stroke-width: 2.4; }
  /* 2026-06-28: Käsi-nappi yläpalkissa — AKTIIVINEN selvästi erottuva (täysi aksenttitäyttö,
     valkoinen ikoni). Vaalea sinitausta ei erottunut valkoisesta palkista (käyttäjäpalaute). */
  #canvas-viewbar #rb-pan-btn.active,
  #canvas-viewbar #rb-pan-btn[aria-pressed="true"] {
    background: var(--canvas-accent, #1565C0) !important; border-color: var(--canvas-accent, #1565C0) !important; color: #fff !important;
  }
  #canvas-viewbar #rb-pan-btn.active svg,
  #canvas-viewbar #rb-pan-btn[aria-pressed="true"] svg { stroke: #fff !important; }
  /* PAN-tila (Käsi-työkalu): KAKSISÄVYINEN SVG-kursori (tumma viiva + paksu valkoinen halo)
     — 2026-07-02 #18 käyttäjäpalaute: natiivi grab hukkui valkoiseen piirustuspohjaan.
     (Historia: 2026-06-11 kokomusta erikois-SVG poistettiin → natiivi; nyt kaksisävy joka
     näkyy sekä valkoisella että tummalla.) Fallback natiiviin grab/grabbing. */
  html body.pan-tool #viewport-wrap,
  html body.pan-tool #viewport-wrap * { cursor: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg stroke='%23fff' stroke-width='4.6'%3E%3Cpath d='M18 11V6a2 2 0 0 0-4 0v5'/%3E%3Cpath d='M14 10V4a2 2 0 0 0-4 0v2'/%3E%3Cpath d='M10 10.5V6a2 2 0 0 0-4 0v8'/%3E%3Cpath d='M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15'/%3E%3C/g%3E%3Cg stroke='%230F1F3A' stroke-width='2'%3E%3Cpath d='M18 11V6a2 2 0 0 0-4 0v5'/%3E%3Cpath d='M14 10V4a2 2 0 0 0-4 0v2'/%3E%3Cpath d='M10 10.5V6a2 2 0 0 0-4 0v8'/%3E%3Cpath d='M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E") 13 13, grab !important; }
  /* Panorointi käynnissä (Käsi-veto TAI keskinäppäin) → suljettu nyrkki, sama kaksisävy. Sääntö on
     pan-tool-säännön JÄLKEEN → voittaa saman spesifisyyden ja näkyy koko vedon ajan. */
  html body.panning #viewport-wrap,
  html body.panning #viewport-wrap * { cursor: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg stroke='%23fff' stroke-width='4.6'%3E%3Cpath d='M18 11.5V9a2 2 0 0 0-2-2 2 2 0 0 0-2 2v1.4'/%3E%3Cpath d='M14 10V8a2 2 0 0 0-2-2 2 2 0 0 0-2 2v2'/%3E%3Cpath d='M10 9.9V9a2 2 0 0 0-2-2 2 2 0 0 0-2 2v5'/%3E%3Cpath d='M6 14a2 2 0 0 0-2-2 2 2 0 0 0-2 2'/%3E%3Cpath d='M18 11a2 2 0 1 1 4 0v3a8 8 0 0 1-8 8h-4a8 8 0 0 1-8-8 2 2 0 1 1 4 0'/%3E%3C/g%3E%3Cg stroke='%230F1F3A' stroke-width='2'%3E%3Cpath d='M18 11.5V9a2 2 0 0 0-2-2 2 2 0 0 0-2 2v1.4'/%3E%3Cpath d='M14 10V8a2 2 0 0 0-2-2 2 2 0 0 0-2 2v2'/%3E%3Cpath d='M10 9.9V9a2 2 0 0 0-2-2 2 2 0 0 0-2 2v5'/%3E%3Cpath d='M6 14a2 2 0 0 0-2-2 2 2 0 0 0-2 2'/%3E%3Cpath d='M18 11a2 2 0 1 1 4 0v3a8 8 0 0 1-8 8h-4a8 8 0 0 1-8-8 2 2 0 1 1 4 0'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E") 13 13, grabbing !important; }
  body.pan-tool #cad-cross-h,
  body.pan-tool #cad-cross-v,
  body.pan-tool #cad-cross-c { display: none !important; }
  /* Erotin nappi-rivien välissä — ohuempi ja matalampi kuin ennen */
  .ribbon-tool-divider {
    width: 1px; height: 26px; background: var(--border); margin: 0 3px; flex-shrink: 0;
  }
  /* 2026-05-24i: Modaalien yläpalkki-napit (Estimaattori, Mallit, Rekisteri, jne.)
     Yhtenäinen tyyli: ikoni + teksti, valkoinen tausta + harmaa reuna,
     hover oranssi. Primary-variantti = tumma navy tausta + valkoinen teksti. */
  .modal-action-btn {
    background: rgba(15,31,58,0.06);
    color: #0F1F3A;
    border: 1px solid #CBD5E1;
    border-radius: 7px;
    padding: 5px 11px;
    cursor: pointer;
    font-size: 12px; font-weight: 600;
    font-family: inherit;
    display: inline-flex; align-items: center; gap: 6px;
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.08s;
  }
  .modal-action-btn:hover {
    background: var(--panel);
    border-color: var(--blue);
    color: var(--blue);
    transform: translateY(-1px);
  }
  .modal-action-btn:active { transform: translateY(0); }
  .modal-action-btn svg { stroke: currentColor; flex-shrink: 0; }
  /* Primary: pää-aktiotille (esim. Päivitä, Tallenna) */
  .modal-action-btn.modal-action-primary {
    background: #0F1F3A; color: #fff; border-color: #0F1F3A;
  }
  .modal-action-btn.modal-action-primary:hover {
    background: var(--blue); border-color: var(--blue); color: #fff;
  }
  /* 2026-05-24k: Projektipalkin napit — kompakti, valkoinen tausta + ohut reuna,
     oranssi hover. Primary-variantti (Estimaattori) = oranssi tausta + valkoinen
     teksti, koska Estimaattori on koko ohjelman pää-CTA. */
  .project-btn {
    background: transparent;
    color: var(--text-muted);
    border: 1px solid transparent;
    height: 28px;
    padding: 0 10px;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: 11px; font-weight: 600;
    font-family: inherit;
    display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    transition: background 0.12s, border-color 0.12s, color 0.12s, transform var(--dur-press) var(--ease-out);
    white-space: nowrap;
  }
  .project-btn:hover {
    background: #fffaf2;
    border-color: var(--blue);
    color: var(--blue);
  }
  .project-btn svg { stroke: currentColor; flex-shrink: 0; }
  .package-export-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 26px;
    max-width: 240px;
    padding: 0 9px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--panel);
    color: var(--text);
    font-size: 11px;
    font-weight: 650;
    white-space: nowrap;
  }
  .package-export-status[hidden] { display: none; }
  .package-export-status[data-state="done"] {
    border-color: rgba(22, 163, 74, 0.42);
    color: var(--success);
  }
  .package-export-status[data-state="error"] {
    border-color: rgba(220, 38, 38, 0.42);
    color: var(--danger);
  }
  .package-export-spinner {
    display: none;
    width: 11px;
    height: 11px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
  }
  .package-export-status[data-state="running"] .package-export-spinner {
    display: inline-block;
    animation: prep-spin 0.75s linear infinite;
  }
  /* 2026-06-05: .project-btn-icon / -primary -tyylit poistettu — eivät enää käytössä (Sulje-nappi poistettu, Estimaattori = tavallinen rivi) */
  /* 2026-07-10 (yöajo B3): pointer-events:none nielaisi klikin ilman mitään palautetta
     (näytti rikkinäiseltä; app-07.js:n empty-guard ei koskaan edes saanut eventtiä).
     Nyt klikki sallitaan → app-07.js näyttää ohjaavan toastin; not-allowed-kursori +
     neutraloitu hover viestivät ettei välilehti aktivoidu. */
  #product-tabs .ptab.empty { opacity: 0.4; cursor: not-allowed; }
  #product-tabs .ptab.empty:hover { background: transparent; color: var(--text-muted); }
  /* Suodatus tabin mukaan: piilota muut paitsi aktiivinen */
  #product-list[data-tab="products"] .tray-card,
  #product-list[data-tab="products"] .stamp-card,
  #product-list[data-tab="products"] .zone-card,
  #product-list[data-tab="products"] .calc-card,
  #product-list[data-tab="products"] .tab-section-trays,
  #product-list[data-tab="products"] .tab-section-zones,
  #product-list[data-tab="products"] .tab-section-calc,
  #product-list[data-tab="products"] .tab-section-markers { display: none !important; }
  /* Mitat = mittaviivat + reitit (vain tray-card) */
  #product-list[data-tab="trays"] .product-card:not(.tray-card),
  #product-list[data-tab="trays"] .tab-section-products,
  #product-list[data-tab="trays"] .tab-section-zones,
  #product-list[data-tab="trays"] .tab-section-calc,
  #product-list[data-tab="trays"] .tab-section-markers { display: none !important; }
  /* 2026-06-08: Alueet-tab = Tilat (A) + Pinta-alat (P) = zone-card; Laskenta-tab = Z (laskennan rajaus) = calc-card */
  #product-list[data-tab="zones"] .product-card:not(.zone-card),
  #product-list[data-tab="zones"] .tab-section-products,
  #product-list[data-tab="zones"] .tab-section-trays,
  #product-list[data-tab="zones"] .tab-section-calc,
  #product-list[data-tab="zones"] .tab-section-markers { display: none !important; }
  #product-list[data-tab="calc"] .product-card:not(.calc-card),
  #product-list[data-tab="calc"] .tab-section-products,
  #product-list[data-tab="calc"] .tab-section-trays,
  #product-list[data-tab="calc"] .tab-section-zones,
  #product-list[data-tab="calc"] .tab-section-markers { display: none !important; }
  #product-list[data-tab="markers"] .product-card:not(.stamp-card),
  #product-list[data-tab="markers"] .tab-section-products,
  #product-list[data-tab="markers"] .tab-section-zones,
  #product-list[data-tab="markers"] .tab-section-calc,
  #product-list[data-tab="markers"] .tab-section-trays { display: none !important; }
  /* 2026-05-11 KÄYTTÄJÄPYYNTÖ: tuotekortin perusrivi YKSINKERTAINEN —
     vain värihöykky + nimi + määrä + ×. Kaikki toiminnot piilotettu kunnes
     käyttäjä klikkaa korttia → aktiivinen → toiminto-paneeli laajenee ALAS
     selvinä napeissa (ei enää hover-piilotettuja pikkukuvia rivissä).
     Aktiivinen tuote on kerrallaan vain yksi → muut pysyvät kompakteina. */
  .product-actions { display: none; }  /* Vanha hover-action-rivi POISTETTU käytöstä */
  .product-actions-panel {
    display: none;
    flex-direction: column; gap: 4px;
    padding: 5px 6px 6px;
    background: rgba(0,0,0,0.018);
    border-top: 1px solid var(--border);
  }
  .product-card.active .product-actions-panel,
  .product-card.pap-open .product-actions-panel { display: flex; }
  .pap-row {
    display: flex; gap: 3px; flex-wrap: wrap;
  }
  /* 2026-08-03 (M4) KÄYTTÄJÄPYYNTÖ: "Muut asetukset voi jäädä siihen jotenkin eri
     lailla sijoitettuna (esim. rattaalla)." Johdotus/Kirjasto/Manuaali + kattavuus-
     säde-rivi ovat otsikkorivin ⚙-painikkeen takana → varianttirivit saavat kortin
     tilan. Ratas itse piiloutuu (._syncProdGearVisibility → .feature-off) jos sen
     takaa ei löydy yhtään käytettävissä olevaa toimintoa. */
  .pap-gear-panel { display: none; flex-direction: column; gap: 4px; }
  .product-card.pap-open .pap-gear-panel { display: flex; }
  /* 2026-05-24e: pap-btn UUDELLEEN SUUNNITELTU — tekninen vektori-ikoni (SVG, Lucide-tyyli)
     + lyhyt teksti alla. Käyttäjäpyyntö: "Nyt ne ikonit mitkä tei on kuin lapsen tekemtä
     Vaihda tyyli ... teknisellä hienolla tyylillä. Voi olla tekstiä ja ikoni".
     Referenssi: Count/Measure/Zone/Note/Pan -tyylinen toolbar dark theme:ssa, mutta
     Vektoria light theme:ssa (valkoinen tausta, harmaa default, oranssi active). */
  .pap-btn {
    /* 2026-06-04: tasainen 4-sarakkeinen ruudukko (Countfire-siisteys) — ei epätasaista wrappia */
    flex: 0 0 calc(25% - 3px); min-width: 0; max-width: none;
    padding: 3px 2px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 7px;
    cursor: pointer;
    font-family: inherit;
    font-size: 8px;
    font-weight: 600;
    color: var(--text-muted);
    text-align: center;
    line-height: 1.05;
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.08s;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 1px;
    position: relative;
    letter-spacing: -0.01em;
  }
  .pap-btn:hover {
    background: #fffaf2;
    border-color: var(--blue);
    color: var(--blue);
    transform: translateY(-1px);
  }
  .pap-btn:active { transform: translateY(0); }
  .pap-btn.active {
    background: #eef3fb;
    border-color: var(--blue);
    color: var(--blue);
  }
  /* SVG-ikoni — ottaa värin parent:lta (currentColor) → muuttuu hover/active:n mukaan.
     2026-05-24f: kayttajapyynto pienempi 22px → 16px, vie vahemman tilaa */
  .pap-btn svg {
    width: 13px; height: 13px;
    stroke: currentColor;
    flex-shrink: 0;
    display: block;
  }
  /* Tuotekortin "Mallit"-napin laskuri + "Yhdistä"-määrä — pieni pyöreä badge oikeassa yläkulmassa */
  .pap-btn .pap-num {
    position: absolute; top: 1px; right: 2px;
    font-size: 8.5px; font-weight: 700;
    background: var(--text-muted); color: #fff;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    border-radius: var(--radius-lg);
    padding: 0 4px; min-width: 12px; text-align: center;
    line-height: 1.3;
    transition: background 0.15s;
  }
  .pap-btn:hover .pap-num,
  .pap-btn.active .pap-num { background: var(--blue); }
  /* Yhdistä-nappi varoitusversio (keltainen) — jos redundant_count > 0 */
  .pap-btn-warn { background: #fffbeb; border-color: #fcd34d; color: #92400e; }
  .pap-btn-warn:hover { background: #fef3c7; border-color: #f59e0b; color: #78350f; }
  .pap-btn-warn .pap-num { background: #f59e0b; }
  /* 2026-06-04 (UI-audit V3): tuote-detailin toissijaiset toiminnot ⋯-ylivuodossa.
     Ydin (Mallit/Kattavuus/Nimi/⋯) yhdellä rivillä; "Lisää" avaa loput. */
  /* 2026-06-28: "⋯ Lisää" -nappi poistettu — kaikki tuotteen toiminnot näkyvät suoraan (2. rivi) */
  /* A2: redundanssi-badge "yhdistä N" */
  .redundancy-badge {
    background: #fef3c7; color: #92400e;
    font-size: 10px; font-weight: 700;
    padding: 2px 6px; border-radius: var(--radius-lg);
    border: 1px solid #fde68a;
    cursor: pointer; flex-shrink: 0;
    transition: background 0.15s;
  }
  .redundancy-badge:hover { background: #fde68a; }
  .match-badge {
    font-size: 10.5px; font-weight: 700;
    padding: 1px 5px; border-radius: 7px;
    background: var(--blue); color: #fff;
    display: none;
  }
  .match-badge.show { display: inline-block; }
  .prod-expand { background: transparent; border: 0; cursor: pointer; font-size: 13px; color: #999; padding: 1px 3px; line-height: 1; }
  .prod-expand:hover { color: var(--text); }
  .prod-cog { background: transparent; border: 0; cursor: pointer; font-size: 13px; color: #999; padding: 1px 3px; line-height: 1; }
  .prod-cog:hover { color: var(--blue); }
  .prod-lib { background: transparent; border: 0; cursor: pointer; font-size: 13px; color: #999; padding: 1px 3px; line-height: 1; }
  .prod-lib:hover { color: var(--blue); }
  /* +1 manuaali-nappi (2026-05-08) */
  .prod-manual { background: transparent; border: 0; cursor: pointer; font-size: 16px; font-weight: 700; color: #999; padding: 0 4px; line-height: 1; }
  .prod-manual:hover { color: var(--blue); }
  .prod-manual.active { color: var(--blue); background: rgba(15,31,58,0.12); border-radius: var(--radius-sm); }
  body.manual-mode #viewport-wrap { cursor: crosshair !important; }
  body.manual-mode #page-img { cursor: crosshair; }
  /* .prod-del — tyylit yhteisessä .x-btn-säännössä */
  /* Kattavuus-nappi tuotekortissa (aina näkyvissä) */
  .cov-toggle {
    background: transparent; border: 1px solid transparent;
    border-radius: var(--radius-sm); padding: 2px 5px; cursor: pointer;
    font-size: 16px; line-height: 1; color: #ccc;
    /* 2026-07-10 motion-auditti: transition:all → eksplisiittiset propertyt
       (hover/active muuttavat vain näitä kolmea; all animoisi vahingossa
       myös layout-propertyt esim. padding-muutoksessa). */
    flex-shrink: 0; transition: background 0.12s, color 0.12s, border-color 0.12s;
  }
  .cov-toggle:hover { background: var(--bark-light); color: var(--text); border-color: var(--border); }
  .cov-toggle.active { color: var(--blue); background: rgba(127,168,106,0.10); border-color: var(--blue); }

  /* Väriswatch tuotekortissa */
  .color-swatch-btn {
    width: 9px; height: 9px; border-radius: 50%;
    border: 1px solid rgba(0,0,0,0.12);
    cursor: pointer; flex-shrink: 0;
    background: #ccc;
    transition: transform 0.12s;
    outline: none;
    position: relative; /* 2026-06-04 (a11y): klikkialan laajennus alla */
  }
  /* WCAG 2.5.8: nakymaton >=24px klikkiala pienelle vari-swatchille (visuaali 9px ennallaan) */
  .color-swatch-btn::before { content: ''; position: absolute; inset: -8px; border-radius: 50%; }
  .color-swatch-btn:hover { transform: scale(1.5); }

  /* Modaalin väriswatch (isompi) */
  #modal-color-swatch {
    width: 22px; height: 22px; border-radius: 50%;
    border: 2px solid rgba(0,0,0,0.18);
    cursor: pointer; flex-shrink: 0; background: #ccc;
    transition: transform 0.12s;
  }
  #modal-color-swatch:hover { transform: scale(1.2); }

  /* Värinvalinta-popover — 2026-05-24n moderni tyyli
     Iso pyöreä palettiruutu + checkmark valittuna + lift hover + parempi varjostus
     + otsikko ja "Muu väri" -syöte */
  #cp-popover {
    position: fixed; z-index: 3000;
    background: var(--panel); border: 1px solid var(--border);
    border-radius: var(--radius-2xl);
    box-shadow: 0 12px 36px rgba(15,31,58,0.15), 0 2px 6px rgba(15,31,58,0.08);
    padding: 12px;
    width: 244px;
    display: none;
    font-family: inherit;
  }
  #cp-popover.open {
    display: block;
    animation: cp-fade-in 0.15s ease-out;
  }
  @keyframes cp-fade-in {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
  }
  #cp-popover::before {
    content: 'Väri';
    display: block; margin: 0 2px 8px;
    font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
    color: var(--text-muted); text-transform: uppercase;
  }
  #cp-grid {
    display: grid; grid-template-columns: repeat(7, 1fr);
    gap: 5px; margin-bottom: 0;
  }
  .cp-cell {
    width: 100%; aspect-ratio: 1 / 1; border-radius: 50%;
    border: 1.5px solid rgba(0,0,0,0.08);
    cursor: pointer;
    transition: transform 0.12s, border-color 0.12s, box-shadow 0.12s;
    position: relative;
  }
  .cp-cell:hover {
    transform: scale(1.16);
    border-color: rgba(0,0,0,0.30);
    box-shadow: 0 3px 8px rgba(0,0,0,0.15);
    z-index: 1;
  }
  .cp-cell.cp-selected {
    border-color: #fff;
    box-shadow: 0 0 0 2px var(--blue), 0 2px 6px rgba(0,0,0,0.15);
  }
  .cp-cell.cp-selected::after {
    content: '';
    position: absolute; left: 50%; top: 50%;
    width: 8px; height: 4px;
    border-left: 2px solid #fff; border-bottom: 2px solid #fff;
    transform: translate(-50%, -65%) rotate(-45deg);
    filter: drop-shadow(0 1px 1px rgba(0,0,0,0.4));
  }
  #cp-divider {
    border: none; border-top: 1px solid var(--border);
    margin: 10px 0 8px;
  }
  #cp-custom-row {
    display: flex; align-items: center; gap: 8px;
    font-size: 11px; color: var(--text-muted);
    padding: 0 2px;
  }
  #cp-custom-row::before {
    content: 'Muu väri:';
    font-weight: 600;
  }
  #cp-custom-input {
    width: 30px; height: 30px; border-radius: var(--radius-lg);
    border: 1.5px solid var(--border);
    cursor: pointer; padding: 2px;
    transition: border-color 0.12s, box-shadow 0.12s;
  }
  #cp-custom-input:hover {
    border-color: var(--blue);
    box-shadow: 0 0 0 2px rgba(15,31,58,0.15);
  }

  /* Template thumbnails */
  .template-grid {
    display: none;
    padding: 5px 8px 8px;
    flex-wrap: wrap;
    gap: 4px;
    border-top: 1px solid #f0eee8;
    background: #fafaf7;
  }
  .template-grid.show { display: flex; }
  .template-thumb {
    width: 46px; height: 46px;
    border: 1px solid #ddd;
    background: var(--panel);
    cursor: pointer;
    border-radius: 3px;
    object-fit: contain;
  }
  .template-thumb:hover { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(15,158,213,0.3); }
  .tgrid-del {
    width: 28px; height: 46px;
    border: 1px solid #fcc; background: #fff8f8;
    border-radius: 3px; cursor: pointer;
    font-size: 16px; color: #e00;
    display: flex; align-items: center; justify-content: center;
  }
  .tgrid-del:hover { background: #fee; }
  .tgrid-row { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; width: 100%; }
  .linked-thumb {
    width: 36px; height: 36px;
    border: 2px dashed var(--blue);
  }
  .linked-thumb:hover { border-color: #c00; box-shadow: 0 0 0 2px rgba(15,31,58,0.3); }
  .add-link-btn {
    height: 46px; padding: 0 8px;
    border: 1px dashed var(--blue); background: #fff8e8;
    border-radius: 3px; cursor: pointer;
    font-size: 11px; color: var(--blue); font-weight: 600;
  }
  .add-link-btn:hover { background: #ffe4c4; }
  body.space-held #viewport-wrap { cursor: crosshair; }

  /* Piirustustyökalupalkki — Apple-tyyli, hillitty, kompakti */
  /* Kontekstuaalinen piirtopalkki — ilmestyy vain kun piirtotila on päällä */
  /* 2026-06-05: KELLUVA teemattu asetuskortti (oli huomaamaton täysleveä palkki). Ilmestyy piirustuksen
     ylälaitaan keskelle kun työkalu on aktiivinen → parametrit (säde, nimi/koko) selkeästi esillä. */
  /* ===== 2026-06-24 PREMIUM-IKKUNAT — jaetut primitiivit (Erä 1) =====
     Selkeä "instrumentti-ikkuna": navy-otsikko, hiusviiva, selvä varjo,
     monospace-arvot. Additiivinen — ei vaikuta ennen kuin elementti saa luokan. */
  .vk-win { background: var(--panel, #fff); border: 1px solid #DDE3EC; border-radius: 10px;
    box-shadow: 0 8px 24px rgba(15,31,58,.14); overflow: hidden; }
  .vk-win-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px;
    background: #0F1F3A; color: #fff; }
  .vk-win-head .vk-win-title { font-size: 12px; font-weight: 500; letter-spacing: .01em;
    white-space: nowrap; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .vk-win-head .vk-win-meta { font-family: ui-monospace, monospace; font-size: 11px;
    color: #8FA3C0; white-space: nowrap; flex: none; }
  .vk-win-head .vk-win-btn { background: transparent; border: 0; color: #8FA3C0;
    font-size: 15px; line-height: 1; padding: 2px 5px; cursor: pointer; border-radius: 5px; }
  .vk-win-head .vk-win-btn:hover { color: #fff; background: rgba(255,255,255,.10); }
  .vk-win-body { padding: 11px 12px; font-size: 12px; color: var(--text, #0F1F3A); }
  .vk-win-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
    color: var(--text-muted, #94A3B8); font-weight: 600; }
  .vk-win-val { font-family: ui-monospace, monospace; color: var(--text, #0F1F3A); }
  #ctx-bar {
    display: none; align-items: center; flex-wrap: wrap; gap: 8px;
    position: fixed; right: 8px; top: 98px; left: auto; transform: none; z-index: 140;
    width: 300px; max-width: calc(100vw - 16px);
    background: var(--panel, #fff); border: 1px solid #DDE3EC; border-radius: 10px;
    padding: 0 12px 11px; box-shadow: 0 8px 24px rgba(15,31,58,.14);
  }
  #ctx-bar.visible { display: inline-flex; }
  /* 2026-06-06: piilota ctx-kortti piirron ajaksi (hiiri pohjassa / polyline kesken) → ei peitä piirustusta */
  #ctx-bar.drawing-busy { display: none !important; }
  /* 2026-06-04: aktiivisen työkalun nimi aina vasemmalla → jokainen työkalu antaa yhtenäisen palkin */
  #dt-toolname {
    flex: 1 1 100%; order: -1; box-sizing: border-box;
    margin: 0 -12px 9px; padding: 9px 12px;
    background: #0F1F3A; color: #fff; border-radius: 10px 10px 0 0;
    font-size: 12px; font-weight: 500; letter-spacing: .01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    display: flex; align-items: center; gap: 6px;
  }
  #dt-toolname:empty { display: none; }
  /* 2026-06-13: piirtotyökalujen toimintaohje = NÄKYVÄ kehotus (ei enää himmeä kursiivi-alaviite).
     Käyttäjäpalaute: rivien/nimen täytön jälkeen ei tiennyt että reitti/mittaviiva PIIRRETÄÄN
     klikkaamalla piirustusta → etsi turhaan "hyväksy"-nappia. Tämä on kortin ensisijainen kehotus. */
  #dt-hint {
    flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 500;
    color: var(--text, #0F1F3A); font-style: normal; white-space: normal;
    padding: 4px 0; background: transparent; border: 0;
  }
  #dt-hint:empty { display: none; }
  #dt-cancel, #dt-finish {
    background: var(--blue); color: #fff; border: 0;
    padding: 4px 12px; border-radius: 5px; cursor: pointer;
    font-family: inherit; font-size: 13px; font-weight: 600;
  }
  #dt-cancel { background: var(--bark-warm); }
  /* 2026-06-01 "Piilota tausta" -napin aktiivitila (sininen reuna kun pohja piilossa).
     Vanha Tausta-liukusäädin (#bg-slider-wrap / #bg-opacity-slider) poistettu — korvattu napilla. */
  #hide-bg-btn.active { border-color: var(--blue); color: var(--blue); background: #eef4ff; font-weight: 700; }
  /* 2026-06-11 "Piilota ▾" -valikko: paneeli aukeaa napin ALLE VASEMMALLE (nappi on
     viewbarin vasemmassa reunassa — oletus right:0 valuisi ruudun ulkopuolelle). */
  #hide-menu .hdr-menu-panel { left: 0; right: auto; min-width: 196px; }
  #hide-menu-panel .rb-btn { margin-top: 3px; }
  #hide-menu-panel .rb-btn svg { width: 15px; height: 15px; margin-right: 8px; flex-shrink: 0; }
  #hide-menu-panel .rb-btn.active { border-color: var(--blue); color: var(--blue); background: #eef4ff; font-weight: 700; }
  /* "jokin suodatin päällä" -indikointi valikkonapissa (eri luokka kuin .active = valikko auki) */
  #hide-menu-btn.filt-on { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  /* 2026-06-11 UX: "Laskenta-alue" on tiilen levyttä pidempi → rivitys tavuviivasta + joustava korkeus.
     2026-08-02 raili-järkeistys: rb-zone-btn/rb-note-btn siirtyivät .lt-sub-riveiksi (leveä pudotus,
     ei tarvitse tätä enää) — sama pitkä nimi elää nyt uudessa .lt-group-tiilessä #lt-tile-alue. */
  #lt-tile-alue { height: auto; min-height: 52px; padding-bottom: 5px; }
  #lt-tile-alue > span:not(.lt-caret) { white-space: normal; text-align: center; line-height: 1.12; }
  /* 2026-08-03 (käyttäjän kuvakaappaus: "Laskenta-alue" näkyi muodossa "Laskenta-" + leikattu "alue").
     KAKSI ERILLISTÄ SYYTÄ, molemmat mitattu selaimessa tekstirivien omista laatikoista
     (Range.getClientRects vs. span-laatikon leikkausraja — pelkkä scrollHeight-vertailu
     VALEHTELEE tässä, koska line-height 10,64 px pyöristyy 21/22:ksi):
       1) SPESIFISYYS: yllä oleva #lt-tile-alue (0,1,0,0) hävisi railissa säännölle
          #tool-rail .lt-tile { height: 52px } (0,1,1,0) → tiili jäi 52 px korkeaksi ja
          toinen rivi vuoti yli 4,63 px = puolet rivistä piiloon (= kuvakaappauksen oire).
       2) RIVINKORKEUS: pelkkä korkeuden vapautus jätti vielä 0,38 px ylivuodon SPANIN
          SISÄLLE — line-height 1.12 (9,5 px fontilla 10,64 px) on kapeampi kuin fontin
          todellinen riviruutu. padding EI korjaa tätä (mitattu: 5→8 px ei muuttanut mitään).
          1.25 antaa −0,88 px marginaalin.
     ⚠ Jos lisäät railiin muita monisanaisia tiiliä, ne tarvitsevat saman yliajon. */
  #tool-rail #lt-tile-alue { height: auto; min-height: 52px; padding-bottom: 5px; }
  #tool-rail #lt-tile-alue > span:not(.lt-caret) { line-height: 1.25; }
  /* 2026-06-11 Zoom-kontrollit: kelluva nappirivi piirustuksen oikeassa alanurkassa
     (?-ohjenapin vasemmalla puolella). position:fixed → ei scrollaa kuvan mukana. */
  #zoom-controls { position: fixed; right: 64px; bottom: 14px; z-index: 900; display: flex; gap: 3px; background: var(--panel); border: 1px solid var(--border); border-radius: 9px; padding: 4px; box-shadow: 0 6px 20px rgba(15,31,58,0.14); }
  #zoom-controls button { min-width: 30px; height: 28px; border: 1px solid transparent; background: transparent; border-radius: 6px; cursor: pointer; font-family: inherit; font-size: 15px; font-weight: 700; color: var(--text); line-height: 1; }
  #zoom-controls button:hover { background: #eef4ff; color: var(--blue); border-color: var(--blue); }
  #zoom-controls #zoom-pct { font-size: 11px; font-weight: 600; min-width: 48px; color: var(--text-muted); }
  body.hub-active #zoom-controls { display: none; }
  #hide-menu-count { min-width: 16px; height: 16px; border-radius: 8px; background: var(--blue); color: #fff; font-size: 10px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; padding: 0 4px; }
  /* C1: revisiovertailu */
  #revdiff-btn.active { border-color: var(--blue); color: var(--blue); background: #eef4ff; font-weight: 700; }
  .diff-base-pop { position: fixed; z-index: 4000; background: var(--panel); border: 1px solid #cbd5e1; border-radius: var(--radius-lg); box-shadow: 0 8px 28px rgba(0,0,0,0.18); padding: 6px; min-width: 220px; max-height: 360px; overflow-y: auto; }
  .diff-base-pop .dbp-head { font-size: 11px; font-weight: 700; color: #64748b; padding: 4px 6px 6px; }
  .diff-base-pop .dbp-item { display: block; width: 100%; text-align: left; border: none; background: none; padding: 6px 8px; border-radius: var(--radius-md); font-size: 12px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .diff-base-pop .dbp-item:hover { background: #eef4ff; color: var(--blue); }
  #diff-panel { position: fixed; top: 120px; right: 14px; width: 300px; max-height: 70vh; overflow-y: auto; z-index: 850; background: var(--panel); border: 1px solid #cbd5e1; border-radius: var(--radius-xl); box-shadow: 0 8px 28px rgba(0,0,0,0.16); font-size: 12px; }
  #diff-panel .dp-head { display: flex; justify-content: space-between; align-items: center; font-weight: 700; padding: 10px 12px; border-bottom: 1px solid #eef2f7; background: #f8fafc; border-radius: 10px 10px 0 0; }
  #diff-panel .dp-x { border: none; background: none; font-size: 18px; line-height: 1; cursor: pointer; color: #64748b; padding: 0 2px; }
  #diff-panel .dp-x:hover { color: #d73027; }
  #diff-panel .dp-sub { padding: 6px 12px; color: #64748b; font-size: 11px; word-break: break-all; }
  #diff-panel .dp-warn { margin: 6px 12px; padding: 6px 8px; background: #eef3fb; border: 1px solid #fed7aa; border-radius: var(--radius-md); color: #9a3412; }
  #diff-panel .dp-info { margin: 6px 12px; padding: 6px 8px; background: #eff6ff; border: 1px solid #bfdbfe; border-radius: var(--radius-md); color: #1e40af; }
  #diff-panel .dp-summary { padding: 8px 12px; }
  #diff-panel .dp-affected { padding: 8px 12px; background: #f8fafc; border-top: 1px solid #eef2f7; border-bottom: 1px solid #eef2f7; }
  #diff-panel .dp-list { padding: 4px 0; }
  #diff-panel .dp-row { display: flex; align-items: center; gap: 8px; padding: 5px 12px; cursor: pointer; border-left: 3px solid transparent; }
  #diff-panel .dp-row:hover { background: #f1f5f9; }
  #diff-panel .dp-row.dp-added { border-left-color: #1a9850; }
  #diff-panel .dp-row.dp-removed { border-left-color: #d73027; }
  #diff-panel .dp-row.dp-mixed { border-left-color: #f59e0b; }
  #diff-panel .dp-num { font-weight: 700; min-width: 20px; color: #64748b; }
  #diff-panel .dp-type { flex: 1; }
  #diff-panel .dp-cnt { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: #475569; }
  #diff-panel .dp-empty { padding: 16px 12px; text-align: center; color: #16a34a; }
  #diff-panel .dp-body { padding: 16px 12px; color: #64748b; }
  /* C1 revisiomalli: tiedostolistan revisio-ryhmittely */
  .file-rev-badge { display:inline-block; margin-left:6px; font-size:9px; font-weight:700; color:var(--blue); background:#eef4ff; border-radius: var(--radius-md); padding:1px 5px; vertical-align:middle; }
  .file-rev-badge.arch { color:#9a3412; background:#eef3fb; }
  .file-item.file-rev-archived { opacity:0.62; }
  .file-rev-expander { margin:0 0 2px 0; }
  .file-rev-toggle { display:block; width:100%; text-align:left; border:none; background:none; cursor:pointer; font-size:10px; color:#64748b; padding:2px 8px 2px 26px; }
  .file-rev-toggle:hover { color:var(--blue); }
  .file-rev-olders { border-left:2px solid #e2e8f0; margin-left:14px; }
  .file-rev-menu { border:none; background:none; cursor:pointer; color:#64748B; font-weight:700; font-size:14px; line-height:1; padding:0 4px; }
  .file-rev-menu:hover { color:var(--blue); }
  .rev-menu-pop { position:fixed; z-index:4000; background:var(--panel); border:1px solid #cbd5e1; border-radius: var(--radius-lg); box-shadow:0 8px 28px rgba(0,0,0,0.18); padding:6px; min-width:210px; }
  .rev-menu-pop .rmp-head { font-size:10px; font-weight:700; color:#64748B; padding:3px 8px 5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .rev-menu-pop button { display:block; width:100%; text-align:left; border:none; background:none; padding:7px 10px; border-radius: var(--radius-md); font-size:12px; cursor:pointer; white-space:nowrap; }
  .rev-menu-pop button:hover { background:#eef4ff; color:var(--blue); }
  /* 2026-05-17: threshold-säädin + .th-help-popover-tyylit poistettu (sliderit lukittu 0.92:een) */
  /* TT2: Lukitse-nappi — kun lukko on päällä, korostetaan oranssilla */
  /* 2026-05-07: #lock-matches-btn -tyylit poistettu (lukitusominaisuus poistettu) */

  /* Batch-mode toggle — sininen kun aktiivinen */
  #batch-mode-btn { font-size: 11px; padding: 4px 10px; }
  #batch-mode-btn.active { background: var(--blue); color: #fff; border-color: var(--blue); font-weight: 700; }
  #batch-mode-btn.active:hover { background: #0c87b8; }

  /* PDF-sivun lukko-banneri — näkyy kun aktiivinen PDF on 'done' (vihreä) */
  #pdf-lock-banner {
    position: absolute; top: 16px; left: 50%; transform: translateX(-50%);
    z-index: 50; display: none;
    background: #16a34a; color: #fff;
    padding: 10px 18px 10px 14px; border-radius: var(--radius-xl);
    box-shadow: 0 6px 20px rgba(22, 163, 74, 0.4);
    font-size: 13px; font-weight: 600; letter-spacing: 0.01em;
    align-items: center; gap: 10px;
    animation: pdf-lock-fade 0.25s ease-out;
  }
  #pdf-lock-banner.show { display: inline-flex; }
  #pdf-lock-banner .lock-icon { display: inline-flex; align-items: center; line-height: 1; }
  #pdf-lock-banner .lock-text { line-height: 1.3; }
  #pdf-lock-banner .lock-hint { opacity: 0.85; font-weight: 400; font-size: 11px; }
  #pdf-lock-banner .lock-unlock-btn {
    background: rgba(255,255,255,0.18); border: 1px solid rgba(255,255,255,0.35);
    color: #fff; border-radius: var(--radius-md); padding: 4px 10px; cursor: pointer;
    font-family: inherit; font-size: 11px; font-weight: 600;
    margin-left: 6px; transition: background 0.12s;
  }
  #pdf-lock-banner .lock-unlock-btn:hover { background: rgba(255,255,255,0.3); }
  @keyframes pdf-lock-fade {
    from { opacity: 0; transform: translate(-50%, -8px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
  }
  /* Vihreä reuna PDF-näkymälle kun lukko päällä — toinen visuaalinen vihje */
  #viewport-wrap.pdf-locked { box-shadow: inset 0 0 0 3px #16a34a; }

  /* Batch-jonon paneeli (pohjapalkki) — jätä Tuotteet-paneelille reilusti tilaa oikealle (440px) */
  #batch-queue-panel {
    position: fixed; left: 340px; bottom: 20px; right: 20px;
    background: var(--panel); border: 2px solid var(--blue); border-radius: var(--radius-xl);
    box-shadow: 0 6px 28px rgba(0,0,0,0.18);
    padding: 10px 14px; z-index: 80;
    display: none; flex-direction: column; gap: 8px;
    max-height: 220px;
  }
  /* Pienemmillä näytöillä paneeli pieneksi automaattisesti */
  @media (max-width: 1400px) {
    #batch-queue-panel { right: 20px; }
  }
  #batch-queue-panel.show { display: flex; }
  .batch-queue-head {
    display: flex; align-items: center; gap: 12px;
    font-size: 12px; color: var(--text);
  }
  .batch-queue-head h3 { margin: 0; font-size: 13px; font-weight: 700; }
  .batch-queue-head .spacer { flex: 1; }
  .batch-queue-head button {
    padding: 6px 12px; border: 1px solid var(--border); background: var(--panel);
    border-radius: var(--radius-md); cursor: pointer; font-size: 12px; font-family: inherit;
  }
  .batch-queue-head button.primary { background: var(--blue); color: #fff; border-color: var(--blue); font-weight: 700; }
  .batch-queue-head button.primary:hover { background: #0c87b8; }
  .batch-queue-head button:disabled { opacity: 0.45; cursor: not-allowed; }
  .batch-queue-list {
    display: flex; gap: 8px; overflow-x: auto; padding: 4px 0 6px;
    scrollbar-width: thin;
  }
  .batch-queue-item {
    flex: 0 0 auto; width: 88px; min-height: 88px;
    border: 1.5px solid var(--border); border-radius: var(--radius-md);
    background: #fafafa; padding: 4px; position: relative; cursor: pointer;
    transition: border-color 0.12s;
    display: flex; flex-direction: column; align-items: center; gap: 2px;
  }
  .batch-queue-item:hover { border-color: var(--blue); }
  .batch-queue-item.collected { border-color: var(--text-muted); }
  .batch-queue-item.reviewed { border-color: #16a34a; background: #f0fdf4; }
  .batch-queue-item.rejected { border-color: #dc2626; background: #fef2f2; opacity: 0.6; }
  .batch-queue-item.searched { border-color: var(--blue); background: #eff6ff; }
  .batch-queue-item .num {
    font-size: 11px; font-weight: 700; color: var(--text);
    background: var(--panel); padding: 1px 5px; border-radius: 3px;
  }
  .batch-queue-item svg.thumb {
    width: 70px; height: 50px; display: block;
  }
  .batch-queue-item .info {
    font-size: 9px; color: var(--text-muted); font-family: 'JetBrains Mono', monospace;
  }
  .batch-queue-item .x-btn {
    position: absolute; top: -6px; right: -6px;
    width: 18px; height: 18px; border-radius: 50%; border: 0;
    background: #dc2626; color: #fff; cursor: pointer;
    font-size: 11px; line-height: 1; padding: 0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
  }
  .batch-queue-item.empty { color: var(--text-muted); font-style: italic; padding: 18px 12px; min-width: 140px; }
  /* 2026-06-04: ohjeteksti — selittää Monivalinnan kulun uudelle käyttäjälle */
  .batch-queue-hint { font-size: 11px; color: var(--text-muted); line-height: 1.45; padding: 0 2px; }
  .batch-queue-hint b { color: var(--text); font-weight: 600; }

  /* Numerolaatikot piirustuksessa (collecting-tilassa) */
  .batch-marker {
    position: absolute; pointer-events: auto; cursor: pointer;
    background: rgba(255,255,255,0.95); border: 2px solid var(--text-muted);
    border-radius: 14px; min-width: 22px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 700; color: var(--text);
    transform: translate(-50%, -50%);
    z-index: 30;
    box-shadow: 0 1px 4px rgba(0,0,0,0.15);
    transition: transform 0.1s;
  }
  .batch-marker:hover { transform: translate(-50%, -50%) scale(1.15); border-color: var(--blue); }
  .batch-marker.reviewed { border-color: #16a34a; background: #f0fdf4; color: #16a34a; }
  .batch-marker.rejected { border-color: #dc2626; background: #fef2f2; color: #dc2626; }
  .batch-marker.searched { border-color: var(--blue); background: #eff6ff; color: var(--blue); }
  /* M-fonttikoko ctx-barissa */
  #m-fontsize-wrap { display:none; align-items:center; gap:4px; border-left:1px solid var(--border); padding-left:8px; }
  #m-fontsize-wrap label { font-size:11px; color:var(--text-muted); }
  /* 2026-06-04: Mittaviivan säde inline kontekstipalkissa (korvaa erillisen popupin) */
  #dt-radius-wrap { display:none; align-items:center; gap:5px; border-left:1px solid var(--border); padding-left:8px; }
  #dt-radius-wrap label { font-size:11px; color:var(--text-muted); white-space:nowrap; }
  #dt-radius-input { width:58px; padding:3px 6px; border:1px solid var(--border); border-radius:5px; font-size:12px; font-family:inherit; }
  #dt-radius-input:focus { outline:none; border-color:var(--blue,#0F9ED5); }
  /* 2026-06-06: Reitti/hyllyt — INLINE monirivieditori ctx-kortissa (korvaa erillisen tray-name-popupin).
     Kaikki hyllyvalinnat tehdään tässä yhdessä kortissa; piirto ei avaa toista modaalia. */
  #dt-tray-wrap { display:none; flex-direction:column; align-items:stretch; gap:6px; flex-basis:100%; border-top:1px solid var(--border); margin-top:2px; padding-top:7px; }
  #dt-tray-wrap .dt-tray-head { font-size:11px; font-weight:700; color:var(--text); }
  #dt-tray-wrap .dt-tray-sub { font-weight:400; color:var(--text-muted); }
  #dt-tray-rows { display:flex; flex-direction:column; gap:5px; }
  .dt-tray-row { display:flex; align-items:center; gap:6px; }
  .dt-tray-row .dt-tray-dot { width:13px; height:13px; border-radius:50%; flex-shrink:0; border:1.5px solid rgba(0,0,0,0.12); }
  .dt-tray-row input.dt-tray-rname { flex:2; padding:4px 7px; border:1px solid var(--border); border-radius:5px; font-size:12px; font-family:inherit; }
  .dt-tray-row input.dt-tray-rkoko { flex:1; min-width:58px; padding:4px 7px; border:1px solid var(--border); border-radius:5px; font-size:12px; font-family:inherit; }
  .dt-tray-row input:focus { outline:none; border-color:var(--blue,#0F9ED5); }
  .dt-tray-row .dt-tray-rdel { background:transparent; border:0; cursor:pointer; color:var(--text-muted); padding:2px 5px; font-size:13px; line-height:1; border-radius:4px; }
  .dt-tray-row .dt-tray-rdel:hover { background:#fde8e8; color:#dc2626; }
  #dt-tray-add { align-self:flex-start; background:#f1f5f9; color:var(--text); border:1px dashed var(--border); border-radius:6px; padding:4px 11px; cursor:pointer; font-size:11.5px; font-weight:600; font-family:inherit; }
  #dt-tray-add:hover { background:#e2e8f0; }
  #m-fontsize-input { width:42px; font-size:12px; padding:2px 4px; border:1px solid var(--border); border-radius: var(--radius-sm); text-align:center; }
  /* 2026-06-06: Muistiinpanon teksti INLINE ctx-kortissa (korvaa erillisen comment-input-popupin) */
  #dt-comment-wrap { display:none; align-items:center; gap:5px; border-left:1px solid var(--border); padding-left:8px; }
  #dt-comment-wrap label { font-size:11px; color:var(--text-muted); white-space:nowrap; }
  #dt-comment-input { width:200px; padding:3px 7px; border:1px solid var(--border); border-radius:5px; font-size:12px; font-family:inherit; }
  #dt-comment-input:focus { outline:none; border-color:var(--blue,#0F9ED5); }
  /* 2026-06-06: Mittaviivan (L/H) nimi+kerroin ja Alueen (Z/A/P) nimi INLINE ctx-kortissa
     (korvaavat measure-confirm- ja zone-name-popupit → ei toista modaalia piirron jälkeen) */
  #dt-meas-wrap, #dt-zone-wrap { display:none; align-items:center; gap:5px; border-left:1px solid var(--border); padding-left:8px; }
  #dt-meas-wrap label, #dt-zone-wrap label { font-size:11px; color:var(--text-muted); white-space:nowrap; }
  #dt-meas-input { width:150px; padding:3px 7px; border:1px solid var(--border); border-radius:5px; font-size:12px; font-family:inherit; }
  #dt-meas-mult { width:46px; padding:3px 6px; border:1px solid var(--border); border-radius:5px; font-size:12px; font-family:inherit; text-align:center; }
  #dt-zone-input { width:170px; padding:3px 7px; border:1px solid var(--border); border-radius:5px; font-size:12px; font-family:inherit; }
  #dt-meas-input:focus, #dt-meas-mult:focus, #dt-zone-input:focus { outline:none; border-color:var(--blue,#0F9ED5); }
  body.drawing-mode #viewport-wrap { cursor: crosshair; }
  /* 2026-06-05: on-canvas sininen ohjepalkki POISTETTU — työkalun nimi + parametrit näkyvät jo ctx-kortissa, ei toistoa/verbose-ohjetta */
  /* 2026-05-07: CAD-tyylinen koko-ruudun tähtäin (kuten CountFire / AutoCAD) — näkyy
     AINA kun hiiri on viewport-wrap:n päällä, EI valikoissa tai napeissa.
     Aktivointi JS:llä body.cad-cross-on -luokan kautta. */
  html body.cad-cross-on #viewport-wrap,
  html body.cad-cross-on #viewport-wrap * { cursor: none !important; }
  #cad-cross-h, #cad-cross-v {
    position: fixed; pointer-events: none; z-index: 9990;
    background: rgba(15,31,58,0.65); display: none;
  }
  #cad-cross-h { left: 0; right: 0; height: 1px; }
  #cad-cross-v { top: 0; bottom: 0; width: 1px; }
  #cad-cross-c {
    position: fixed; pointer-events: none; z-index: 9991;
    width: 18px; height: 18px;
    transform: translate(-50%, -50%); display: none;
  }
  #cad-cross-c::before, #cad-cross-c::after {
    content: ''; position: absolute; background: rgba(15,31,58,0.92);
  }
  #cad-cross-c::before { left: 0; right: 0; top: 50%; height: 1.5px; transform: translateY(-50%); }
  #cad-cross-c::after { top: 0; bottom: 0; left: 50%; width: 1.5px; transform: translateX(-50%); }
  body.cad-cross-on #cad-cross-h,
  body.cad-cross-on #cad-cross-v,
  body.cad-cross-on #cad-cross-c { display: block; }
  /* Piirustuskerros PDF:n päälle */
  #draw-overlay { pointer-events: none; }
  /* ── 2026-06-11 Mittausten hover-linkitys + hallinta (käyttäjäpalaute) ──────
     Pituus-chipit piilossa oletuksena (lukema on tulosluettelossa) → näkyviin
     hoverilla TAI listarivin hoverilla (.meas-hl). Leveä näkymätön hit-stroke
     tekee ohuesta viivasta helposti osoitettavan. Glow = korostus molempiin
     suuntiin (viiva ↔ listarivi, tuotekortti ↔ symbolit). */
  #draw-overlay .meas-g { pointer-events: none; }
  #draw-overlay .meas-hit { pointer-events: stroke; cursor: pointer; }
  #draw-overlay .meas-chip { display: none; }
  /* Kuvan-hover → pituus näkyy KURSORIN kohdalla (#ml-cursor-tip), ei kaukana keskellä.
     Listarivin-hover (.meas-hl) näyttää keskikohtachipin = paikannus kuvassa. */
  #draw-overlay .meas-g.meas-hl .meas-chip,
  #draw-overlay .meas-g:hover .meas-chip { display: block; }   /* 2026-06-22: mitta näkyy myös viivaa hoveroidessa */
  #draw-overlay .meas-g:hover, #draw-overlay .meas-g.meas-hl { filter: drop-shadow(0 0 4px rgba(21,101,192,0.85)); }
  /* 2026-06-11b KORJAUS (käyttäjäpalaute "ei korosta mitään"): rivikorostus selvästi
     näkyväksi (tausta + reunus) ja match-korostus NÄKYVÄKSI myös oletustilassa, jossa
     data-match-idx-rect on fill=transparent ilman strokea → pelkkä stroke-width/glow
     oli kirjaimellisesti näkymätön. */
  .tray-card.row-hl, .product-card.row-hl { outline: 2px solid var(--blue); outline-offset: -2px; border-radius: 6px; background: #EAF2FE; }
  #match-layer .match-hl { stroke: #1565c0 !important; stroke-width: 3px !important;
    fill: rgba(21,101,192,0.14) !important; filter: drop-shadow(0 0 5px rgba(21,101,192,0.8)); }
  /* 2026-06-11 V2 (Task D): alueet + kommentit osoitettaviksi — polygonit vain
     reunastaan (stroke) jotta alueen SISÄLLÄ piirto/klikkaus toimii ennallaan */
  #draw-overlay polygon[data-zone-idx] { pointer-events: stroke; cursor: pointer; }
  #draw-overlay rect[data-zone-idx] { pointer-events: all; cursor: pointer; }
  #draw-overlay [data-comment-idx] { pointer-events: all; cursor: pointer; }
  /* 2026-06-11 V2 (Task E): valitun mittauksen muokkauskahvat */
  #draw-overlay .meas-handle { fill: #fff; stroke: var(--canvas-accent); stroke-width: 2; cursor: grab; pointer-events: all; r: var(--vk-handle-r, 6px); }
  #draw-overlay .meas-handle:hover { fill: #DBE5F0; }
  /* 2026-06-23: VÄLIPISTE-kahva (segmentin keskellä) — enemmän tartuntapisteitä johdotuksen
     muokkaukseen. Pienempi + läpikuultava → erottuu kulmakahvasta; vetämällä lisää pisteen. */
  #draw-overlay .meas-handle-mid { fill: var(--canvas-accent); fill-opacity: 0.4; stroke: var(--canvas-accent); stroke-width: 1.5; r: var(--vk-handle-mid-r, 5px); }
  #draw-overlay .meas-handle-mid:hover { fill-opacity: 0.8; }
  #draw-overlay .meas-g.meas-editing { filter: drop-shadow(0 0 4px rgba(21,101,192,0.85)); }
  #match-layer .match-hl { stroke-width: 4px !important; filter: drop-shadow(0 0 5px rgba(21,101,192,0.8)); }
  #meas-ctx-menu { position: fixed; z-index: 2000; background: var(--panel); border: 1px solid var(--border);
    border-radius: 8px; box-shadow: 0 8px 28px rgba(0,0,0,0.25); padding: 4px; min-width: 200px; }
  #meas-ctx-menu .mcm-title { padding: 5px 10px 4px; font-size: 11px; font-weight: 700; color: var(--text-muted);
    border-bottom: 1px solid var(--border-soft); margin-bottom: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
  #meas-ctx-menu button { display: block; width: 100%; text-align: left; padding: 6px 10px; border: 0;
    background: transparent; border-radius: 5px; cursor: pointer; font-family: inherit; font-size: 12.5px; color: var(--text); }
  #meas-ctx-menu button:hover { background: var(--panel-soft); }
  #meas-ctx-menu .mcm-danger:hover { background: #FDECEC; color: #B3261E; }
  #draw-overlay .draw-line { stroke: var(--canvas-accent); stroke-width: 2.5; fill: none; stroke-linecap: round; stroke-linejoin: round; }
  #draw-overlay .draw-line-halo { stroke: #ffffff; stroke-width: 6; fill: none; stroke-linecap: round; stroke-linejoin: round; stroke-opacity: 0.75; }
  /* Z = laskenta-alue: tummennus ULKOPUOLELLE, oranssi paksu reuna
     2026-05-26 poisrajaus: tummennus 0.32 → 0.18 (ei näytä harmaalta) ja
     erillinen ohut reuna poisrajauksille (sisäalueet jotka jätetään ulkopuolelle) */
  #draw-overlay .zone-dim-rect { fill: rgba(0,0,0,0.18); pointer-events: none; }
  #draw-overlay .zone-border-Z { fill: none; stroke: var(--canvas-accent); stroke-width: 3.5; stroke-dasharray: none; stroke-linecap: round; stroke-linejoin: round; }
  #draw-overlay .zone-border-Z-hole { fill: none; stroke: var(--canvas-accent); stroke-width: 2.5; stroke-dasharray: 6,4; stroke-linecap: round; stroke-linejoin: round; opacity: 0.85; }
  /* 2026-05-29 poisrajaus-kohde: animoituva korostus jotta käyttäjä tietää MIHIN reikä menee */
  #draw-overlay .zone-subtract-target { animation: zoneSubtractPulse 1.2s ease-in-out infinite; }
  @keyframes zoneSubtractPulse { 0%,100% { stroke-opacity: 1; fill-opacity: 1; } 50% { stroke-opacity: 0.45; fill-opacity: 0.5; } }
  /* A = Tila-alue: täyte SISÄPUOLELLE, sininen katkoviivareuna, iso teksti */
  #draw-overlay .zone-fill-A { fill: rgba(15,158,213,0.18); stroke: #0F9ED5; stroke-width: 2; stroke-dasharray: 8,5; stroke-linecap: round; stroke-linejoin: round; }
  /* P = Pinta-ala (m²): vihreä vaalea täyttö, ohut yhtenäinen reuna, iso m²-teksti */
  #draw-overlay .zone-fill-P { fill: rgba(22,163,74,0.18); stroke: #16A34A; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
  #draw-overlay .zone-label-text { font-size: 14px; font-weight: 700; fill: var(--text); paint-order: stroke; stroke: #fff; stroke-width: 3; stroke-linejoin: round; pointer-events: none; }
  /* A-alueen iso sisäinen nimikenttä */
  #draw-overlay .pa-label-bg { fill: rgba(15,158,213,0.12); stroke: #0F9ED5; stroke-width: 1; rx: 6; }
  #draw-overlay .pa-label-text { font-size: 18px; font-weight: 800; fill: #0F9ED5; text-anchor: middle; dominant-baseline: central; paint-order: stroke; stroke: rgba(255,255,255,0.9); stroke-width: 4; stroke-linejoin: round; pointer-events: none; letter-spacing: 0.5px; }
  #draw-overlay .draw-marker { stroke: #fff; stroke-width: 1.5; }
  #draw-overlay .draw-length-label { font-size: 16px; font-weight: 700; font-family: inherit; }
  /* Ribbon piirtonapit */
  /* 2026-05-24j KORJAUS: rajaa .rb-dt -saannot pois uusilta .ribbon-btn-napilta jotta
     CAD-tyyli (8.5px fontti, kompaktimpi koko) ei ylikirjoitu vanhalla 50px/34px-koolla.
     Vanha tyyli sailoa muille .rb-dt-napeille (jos viela kayttoa). */
  .dt-btn, .rb-dt:not(.ribbon-btn) {
    position: relative;
    background: var(--bg);
    border: 1px solid var(--border);
    padding: 0;
    width: 50px; height: 34px;
    border-radius: var(--radius-md);
    font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s, transform 0.1s, box-shadow 0.1s;
    color: var(--text);
    font-family: 'JetBrains Mono', monospace;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .rb-dt:not(.ribbon-btn):hover {
    background: var(--bark-light);
    border-color: var(--bark-warm);
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(0,0,0,0.10);
  }
  .rb-dt:not(.ribbon-btn).active {
    background: var(--blue); border-color: var(--leaf-deep); color: #fff;
    box-shadow: 0 1px 4px rgba(127,168,106,0.25);
    transform: none;
  }
  /* Z = laskenta-alue — korostettu, oranssi (vanha .rb-dt-zone, ei kosketa .ribbon-btn:ia) */
  .rb-dt-zone:not(.ribbon-btn) { border-color: var(--blue) !important; color: var(--blue); font-weight: 800; background: rgba(15,31,58,0.07); }
  .rb-dt-zone:not(.ribbon-btn):hover { background: rgba(15,31,58,0.15) !important; border-color: var(--blue) !important; box-shadow: 0 3px 10px rgba(15,31,58,0.18) !important; }
  .rb-dt-zone:not(.ribbon-btn).active { background: var(--blue) !important; border-color: var(--blue) !important; color: #fff; box-shadow: 0 2px 8px rgba(15,31,58,0.35) !important; }
  /* Tooltip hover — kaikille rb-dt-napeille */
  .rb-dt[data-tip]::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%; transform: translateX(-50%) translateY(4px);
    background: #1c1c1e; color: #f5f5f7;
    font-size: 11px; font-weight: 500; letter-spacing: 0.02em;
    font-family: inherit;
    padding: 5px 10px; border-radius: var(--radius-md);
    white-space: nowrap; pointer-events: none;
    opacity: 0; transition: opacity 0.15s, transform 0.15s;
    z-index: 9999;
    box-shadow: 0 4px 12px rgba(0,0,0,0.22);
  }
  .rb-dt[data-tip]::before {
    content: '';
    position: absolute;
    bottom: calc(100% + 5px); left: 50%;
    transform: translateX(-50%) translateY(4px);
    border: 5px solid transparent; border-top-color: #1c1c1e;
    pointer-events: none; opacity: 0;
    transition: opacity 0.15s, transform 0.15s;
    z-index: 9999;
  }
  .rb-dt[data-tip]:hover::after {
    opacity: 1; transform: translateX(-50%) translateY(0);
  }
  .rb-dt[data-tip]:hover::before {
    opacity: 1; transform: translateX(-50%) translateY(0);
  }
  /* 2026-05-21: Projektipalkin napit — hienovarainen hover */
  #project-bar button:hover { background: rgba(15,31,58,0.12) !important; }
  #project-bar button:active { background: rgba(15,31,58,0.18) !important; transform: translateY(1px); }
  /* 2026-05-21: Estimaattorin otsikkopalkin napit */
  #estimate-excel-btn:hover, #estimate-laskenta-btn:hover, #estimate-close:hover { background: rgba(15,31,58,0.14) !important; }
  #estimate-refresh-btn:hover { background: #1E293B !important; }

  /* 2026-05-21: Globaali kaunis tooltip — korvaa selaimen ruman default-tooltipin
     kaikille elementeille joilla title="..." -attribuutti. JS-helper alla. */
  #_tt {
    position: fixed;
    z-index: 100000;
    background: #1c1c1e;
    color: #f5f5f7;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.01em;
    padding: 7px 12px;
    border-radius: 7px;
    pointer-events: none;
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.18s ease, transform 0.18s ease;
    box-shadow: 0 6px 20px rgba(0,0,0,0.28), 0 2px 6px rgba(0,0,0,0.16);
    max-width: 320px;
    line-height: 1.45;
    white-space: pre-wrap;
    display: none;
  }
  #_tt.show {
    opacity: 1;
    transform: translateY(0);
  }
  /* 2026-05-11: mm/cm/m -yksikkö-toggle Merkkaa-ryhmässä. Kompakti segmentti
     joka näyttää aktiivisen yksikön korostetusti. Vaikuttaa kaikkiin mittauksiin.
     2026-05-12: korkeus 34px → samaan linjaan muun ribbonin kanssa (Batch, MERKKAA). */
  .rb-unit-toggle {
    display: inline-flex; align-items: stretch; gap: 0;
    height: 34px;
    border: 1px solid var(--border); border-radius: var(--radius-md);
    background: var(--btn-sec-bg); overflow: hidden;
    margin-right: 6px;
  }
  .rb-unit-toggle .rb-unit-btn {
    background: transparent; border: 0; cursor: pointer;
    padding: 0 9px; font-size: 11px; font-weight: 700;
    color: var(--text-muted); font-family: 'JetBrains Mono', ui-monospace, monospace;
    border-right: 1px solid var(--border); letter-spacing: 0.08em; text-transform: uppercase;
    transition: background 0.1s, color 0.1s;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 30px;
  }
  .rb-unit-toggle .rb-unit-btn:last-child { border-right: 0; }
  .rb-unit-toggle .rb-unit-btn:hover { background: rgba(0,0,0,0.04); color: var(--text); }
  .rb-unit-toggle .rb-unit-btn.active {
    background: var(--btn-bg); color: var(--btn-fg);
  }
  /* Pikanäppäin-merkki flyout-itemissä — pieni vihje näppäimestä */
  .fi-kbd {
    display: inline-block; margin-left: 6px;
    padding: 1px 5px; font-size: 9px; font-weight: 700;
    background: rgba(0,0,0,0.06); color: var(--text-muted);
    border-radius: 3px; font-family: 'JetBrains Mono', ui-monospace, monospace;
    letter-spacing: 0;
  }
  /* Flyout — MERKKAA-valitsin (2026-05-12 UI-yhtenäistys: pillinmuotoinen pudotusvalikko-laukaisija
     joka mätsää muun ribbonin nappityyleihin (Batch, Lataa). Ei enää neliön muotoinen 50px-laatikko. */
  .dt-flyout { position: relative; display: inline-block; }
  #line-flyout-btn {
    width: auto; min-width: 96px; height: 34px;
    padding: 0 14px; gap: 7px;
    letter-spacing: 0.08em;
    background: var(--bg);
  }
  #line-flyout-btn .ft-label {
    font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  }
  #line-flyout-btn .ft-chevron {
    font-size: 10px; opacity: 0.55; line-height: 1;
    margin-top: 1px;
  }
  #line-flyout-btn:hover .ft-chevron { opacity: 0.85; }
  #line-flyout-btn.active .ft-chevron { opacity: 0.95; }
  .dt-flyout-menu {
    display: none;
    position: absolute;
    top: calc(100% + 6px); left: 50%;
    transform: translateX(-50%);
    background: var(--panel);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    padding: 8px; min-width: 280px;
    box-shadow: 0 8px 28px rgba(0,0,0,0.16);
    z-index: 9999;
  }
  .dt-flyout-menu.open { display: flex; flex-direction: column; gap: 2px; }
  /* 2026-05-08 UI-siivous v2: ammattimainen flyout, kolme sektiota (Mittaa/Alueet/Merkinnät),
     tasaus selkeä (fi-key kiinteä leveys vasemmalla, fi-desc venyy oikealle) */
  .dt-flyout-section { display: flex; flex-direction: column; gap: 1px; }
  .dt-flyout-section + .dt-flyout-section {
    margin-top: 8px; padding-top: 8px;
    border-top: 1px solid var(--border);
  }
  .dt-flyout-section-title {
    font-size: 9px; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--text-muted); padding: 2px 8px 6px; user-select: none;
  }
  .dt-flyout-item {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 5px 9px;
    height: auto;
    border: 1px solid transparent; border-radius: 5px;
    background: transparent; cursor: pointer;
    font-family: 'JetBrains Mono', monospace;
    transition: background 0.1s, border-color 0.1s; text-align: left;
  }
  /* 2026-05-24g/h: SVG-ikoni flyout-itemin alussa — kompaktimpi 14px */
  .dt-flyout-item .fi-icon {
    width: 14px; height: 14px; flex-shrink: 0;
    color: var(--text); display: inline-flex; align-items: center; justify-content: center;
  }
  .dt-flyout-item .fi-icon svg { width: 14px; height: 14px; stroke: currentColor; }
  .dt-flyout-item.active .fi-icon { color: #fff; }
  .dt-flyout-item.rb-dt-zone .fi-icon { color: var(--blue); }
  .dt-flyout-item.rb-dt-zone.active .fi-icon { color: #fff; }
  .dt-flyout-item.rb-dt-erase.active .fi-icon { color: #fff; }
  .dt-flyout-item:hover { background: var(--bark-light); border-color: var(--border); transform: none; box-shadow: none; }
  .dt-flyout-item.active { background: var(--blue); border-color: var(--leaf-deep); color: #fff; }
  .dt-flyout-item .fi-key {
    font-size: 10px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
    width: 78px; flex-shrink: 0; text-align: left;
    color: var(--text);
    font-family: 'JetBrains Mono', monospace;
  }
  .dt-flyout-item.active .fi-key { color: #fff; }
  .dt-flyout-item .fi-desc {
    font-size: 9px; font-weight: 500;
    color: var(--text-muted); letter-spacing: 0.05em; text-transform: uppercase;
    line-height: 1.3;
    font-family: 'JetBrains Mono', monospace;
    flex: 1;
  }
  .dt-flyout-item.active .fi-desc { color: rgba(255,255,255,0.85); }
  /* ZONE-rivi (rb-dt-zone) flyoutissa: pidä oranssi key-väri korostuksena, mutta riviä ei väritetä taustaksi */
  .dt-flyout-item.rb-dt-zone { background: transparent !important; }
  .dt-flyout-item.rb-dt-zone .fi-key { color: var(--blue); }
  .dt-flyout-item.rb-dt-zone:hover { background: rgba(15,31,58,0.07) !important; border-color: var(--blue) !important; box-shadow: none !important; }
  .dt-flyout-item.rb-dt-zone.active { background: var(--blue) !important; border-color: var(--blue) !important; }
  .dt-flyout-item.rb-dt-zone.active .fi-key { color: #fff; }
  /* 2026-05-17: PYYHI-työkalu — destruktiivinen, punainen aksentti */
  /* 2026-05-21: Pyyhi-painikkeen väri normaaliksi (oli punainen) */
  .dt-flyout-item.rb-dt-erase.active { background: var(--bark-warm, #64748B) !important; border-color: var(--bark-warm, #64748B) !important; color: #fff; }
  .dt-flyout-item.rb-dt-erase.active .fi-key { color: #fff; }
  #draw-overlay .draw-comment-bg { fill: #fffbe6; stroke: var(--bark-warm); stroke-width: 1; }
  #draw-overlay .draw-comment-text { fill: var(--text); font-size: 12px; font-weight: 600; }
  #draw-overlay .draw-comment-leader { fill: none; stroke-width: 1.5; }
  #draw-overlay .draw-comment-arrow { }
  #draw-overlay .draw-coverage {
    stroke: var(--canvas-accent); stroke-width: 1; stroke-dasharray: 4,3;
    fill: rgba(127,168,106,0.10);
  }
  /* 2026-05-12 #4 KORJAUS: rajoita .draft-line CSS-saanto LINE/SPAN-tyokaluille (cfg.type=polyline jossa
     EI ole tray-band-rakennetta). Tray-varjon kerrokset (leveys + valkoinen ydin + dashed-keskiviiva)
     kayttavat omia inline-stroke/width-attribuutteja jotka CSS pakotti orange/2px/dashed:iin →
     varjo nakyi piirron aikana vain ohuena oranssina pisteviivana, oikea varjo tuli vasta kun
     piirto tallennettiin (renderAnnotations kayttaa eri renderointia ilman .draft-line). */
  #draw-overlay .draft-line:not(.tray-shadow) { stroke: var(--canvas-accent); stroke-width: 2; fill: none; stroke-dasharray: 4,3; }
  #draw-overlay .draft-point { fill: var(--canvas-accent); }
  #draw-overlay .draft-handle { fill: #fff; stroke: var(--canvas-accent); stroke-width: 1.5; }
  /* Annotation panel */
  .ann-section { border-top: 1px solid var(--border); padding: 6px 12px; }
  .ann-section h3 { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); margin: 0 0 4px; }
  /* STAMP-tilan live-counter — näkyy PDF:n yläosassa kun käyttäjä lisää merkkejä manuaalisesti */
  #stamp-counter {
    position: fixed;
    top: 78px;  /* ribbonin alle */
    left: 50%;
    transform: translateX(-50%);
    background: #FFFBEA;
    border: 2px solid #F59E0B;
    border-radius: var(--radius-2xl);
    padding: 10px 16px;
    box-shadow: 0 6px 20px rgba(0,0,0,0.18);
    display: none;
    z-index: 800;
    align-items: center;
    gap: 14px;
    font-size: 13px;
    color: #92400E;
    user-select: none;
  }
  #stamp-counter.show { display: flex; }
  #stamp-counter .sc-icon {
    font-size: 18px;
  }
  #stamp-counter .sc-name {
    font-weight: 700;
    color: #92400E;
  }
  #stamp-counter .sc-count {
    background: #F59E0B;
    color: #fff;
    padding: 3px 10px;
    border-radius: 14px;
    font-weight: 700;
    font-size: 14px;
    min-width: 32px;
    text-align: center;
  }
  #stamp-counter .sc-divider {
    width: 1px;
    height: 22px;
    background: #FCD34D;
  }
  #stamp-counter button {
    background: var(--panel);
    border: 1px solid #FCD34D;
    color: #92400E;
    border-radius: 7px;
    padding: 5px 10px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
  }
  #stamp-counter button:hover {
    background: #FEF3C7;
    border-color: #F59E0B;
  }
  #stamp-counter button.sc-stop {
    background: var(--panel);
    color: #92400E;
  }
  #stamp-counter kbd {
    background: #FEF3C7;
    border: 1px solid #FCD34D;
    border-radius: 3px;
    padding: 1px 5px;
    font-size: 10px;
    font-family: 'JetBrains Mono', monospace;
  }
  /* Manuaali-tilan banneri — näkyy ribbonin alla kun käyttäjä lisää +1-merkintöjä manuaalisesti.
     2026-05-09 käyttäjäpyyntö: "PITÄÄ TIETÄÄ ETTÄ SE ON AKTIIVINEN, KUN TEKEE MANUAALILISÄYKSIÄ" */
  /* 2026-07-21 TEEMABUGI (mitattu, ei paateltu): tummassa teemassa --text on VAALEA
     (#F2F2F5), joten `color: #fff` teki bannerista valkoista valkoisella —
     mitattu tumma: bg rgb(242,242,245) / teksti rgb(255,255,255) = nakymaton.
     --panel on --text:n vastapari kaikissa kolmessa teemassa. */
  #manual-mode-banner {
    position: fixed;
    top: 78px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--text, #0F1F3A);
    color: var(--panel, #fff);
    border-radius: 999px;
    padding: 9px 8px 9px 16px;
    display: none;
    align-items: center;
    gap: 12px;
    z-index: 800;
    font-size: 13px;
    user-select: none;
    box-shadow: 0 6px 20px rgba(0,0,0,0.25);
  }
  #manual-mode-banner.show { display: flex; }
  #manual-mode-banner .mmb-dot {
    width: 12px; height: 12px; border-radius: 50%;
    border: 2px solid var(--panel, #fff);
    flex-shrink: 0;
    animation: mmb-pulse 1.4s ease-in-out infinite;
  }
  @keyframes mmb-pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.25); opacity: 0.75; }
  }
  #manual-mode-banner .mmb-text { font-weight: 700; letter-spacing: 0.2px; }
  #manual-mode-banner .mmb-hint { color: inherit; opacity: 0.55; font-size: 11px; font-weight: 500; }
  #manual-mode-banner .mmb-stop {
    background: var(--panel); color: var(--text, #0F1F3A);
    border: 0; padding: 5px 12px; border-radius: 999px;
    font-size: 12px; font-weight: 600; cursor: pointer;
    font-family: inherit;
  }
  #manual-mode-banner .mmb-stop:hover { background: var(--btn-sec-bg, #F1F5F9); }
  /* Pulssi-rinki viewport-wrapin reunoilla manuaali-tilassa — vahvistaa että tila päällä */
  body.manual-mode #viewport-wrap::after {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    border: 3px solid var(--mm-color, #0F1F3A);
    border-radius: var(--radius-sm);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.6);
    animation: mm-frame-pulse 1.6s ease-in-out infinite;
    z-index: 900;
  }
  @keyframes mm-frame-pulse {
    0%, 100% { opacity: 0.55; }
    50% { opacity: 0.95; }
  }

  /* Uuden tuotteen rajaus-odotus (2026-07-21 käyttäjäpalaute: "vedä laatikko" -teksti
     oli liian pieni eikä tarpeeksi selkeä). Sama pilleri+kehys-malli kuin manuaali-
     tilalla — käyttäjä on jo oppinut sen. Värit tokeneista → tumma teema seuraa. */
  /* TEEMA-ANSA (löytyi tummasta teemasta ennen committia): manuaali-tilan banneri
     käyttää `background: var(--text); color: #fff`, mutta tummassa --text on VAALEA
     → valkoinen teksti valkoisella = näkymätön. --panel on --text:n vastapari
     kaikissa kolmessa teemassa (vaalea: #FFFFFF vs tumma teksti, tumma: #18181C vs
     vaalea teksti), joten pari pysyy kontrastisena kumpaankin suuntaan. */
  #new-product-banner {
    position: fixed; top: 78px; left: 50%; transform: translateX(-50%);
    background: var(--text, #0F1F3A); color: var(--panel, #fff); border-radius: 999px;
    padding: 9px 8px 9px 16px;
    display: none; align-items: center; gap: 12px;
    z-index: 800; font-size: 13px; user-select: none;
    box-shadow: 0 6px 20px rgba(0,0,0,0.25);
    max-width: calc(100vw - 32px);
  }
  #new-product-banner.show { display: flex; }
  #new-product-banner .npb-icon {
    font-size: 16px; line-height: 1; flex-shrink: 0;
    color: var(--npb-color, var(--panel, #fff));
    animation: mmb-pulse 1.4s ease-in-out infinite;
  }
  #new-product-banner .npb-text { font-weight: 700; letter-spacing: 0.2px; white-space: nowrap; }
  /* opacity (ei rgba) → himmennys seuraa perittyä --panel-väriä molemmissa teemoissa */
  #new-product-banner .npb-hint {
    color: inherit; opacity: 0.62; font-size: 11px; font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  #new-product-banner .npb-cancel {
    background: var(--panel); color: var(--text, #0F1F3A);
    border: 0; padding: 5px 12px; border-radius: 999px;
    font-size: 12px; font-weight: 600; cursor: pointer;
    font-family: inherit; flex-shrink: 0; white-space: nowrap;
  }
  #new-product-banner .npb-cancel:hover { background: var(--btn-sec-bg, #F1F5F9); }
  /* Kapea ikkuna: pitkä vihje pois, pilleri ei saa valua ruudun ulkopuolelle */
  @media (max-width: 900px) {
    #new-product-banner .npb-hint { display: none; }
  }
  /* Perifeerinen signaali: sama pulssikehys kuin manuaali-tilassa. Crosshair-kursori
     yksin ei kertonut että ohjelma odottaa toimintoa juuri piirustusalueella. */
  body.awaiting-new-product #viewport-wrap::after {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    border: 3px solid var(--blue);
    border-radius: var(--radius-sm);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.6);
    animation: mm-frame-pulse 1.6s ease-in-out infinite;
    z-index: 900;
  }
  /* Placeholder-kortin ohjerivi — EI .product-metaa, joka on jaettu osumamäärien
     kanssa (nowrap/monospace/oikea tasaus tekivät pitkästä ohjeesta puristetun). */
  .product-card.new-placeholder .npb-row-hint {
    display: flex; align-items: center; gap: 6px;
    font-size: 12px; line-height: 1.35; font-weight: 600;
    color: var(--blue); padding: 2px 8px 7px; white-space: normal;
  }
  .product-card.new-placeholder .npb-row-icon { font-size: 14px; flex-shrink: 0; }
  .product-card.new-placeholder {
    border-left-style: dashed; border-left-width: 4px;
    box-shadow: 0 0 0 2px var(--blue);
  }

  /* OMAT SYMBOLIT -prominentti tyyli — erottuu paneelin yläosassa keltaisella taustalla */
  .ann-section-prominent {
    background: linear-gradient(180deg, #FFFBEA 0%, #FFF7D6 100%);
    border-top: 2px solid #F59E0B;
    border-bottom: 1px solid #FCD34D;
    padding: 8px 12px;
  }
  .ann-section-prominent h3 {
    color: #92400E;
    font-size: 11px;
  }
  .ann-section-prominent .ann-item {
    background: var(--panel);
    border-radius: var(--radius-md);
    padding: 5px 8px;
    margin-bottom: 3px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  }
  .ann-item { display: flex; align-items: center; gap: 6px; padding: 2px 0; font-size: 12px; }
  .ann-item-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ann-del-btn { background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 14px; padding: 1px 3px; border-radius: 3px; flex-shrink: 0; line-height: 1; }
  .ann-del-btn:hover { color: #dc2626; background: #fee2e2; }
  /* OMAT SYMBOLIT — laajennettava per-label hallintapaneeli (2026-05-07) */
  .ann-marker-row { background: var(--panel); border-radius: var(--radius-md); margin-bottom: 4px; box-shadow: 0 1px 2px rgba(0,0,0,0.04); overflow: hidden; }
  .ann-marker-row.expanded { box-shadow: 0 2px 8px rgba(245,158,11,0.25); border: 1px solid #FCD34D; }
  .ann-marker-row .ann-item { padding: 5px 8px; }
  .marker-edit-panel {
    border-top: 1px solid #FCD34D;
    background: #FFFBEA;
    padding: 8px 10px;
    display: flex; flex-direction: column; gap: 6px;
  }
  .mep-row { display: flex; align-items: center; gap: 8px; font-size: 11px; }
  .mep-row label { color: #92400E; font-weight: 600; min-width: 50px; }
  .mep-row input[type=text], .mep-row input[type=number] {
    flex: 1; padding: 4px 7px; border: 1px solid #FCD34D; border-radius: var(--radius-sm);
    font-size: 12px; font-family: inherit; background: var(--panel);
  }
  .mep-row input:focus { outline: 2px solid #F59E0B; outline-offset: -1px; }
  .mep-row-2col { gap: 4px; }
  .mep-row-2col input[type=number] { max-width: 60px; flex: 0 0 auto; }
  .mep-color-swatch {
    width: 24px; height: 24px; border-radius: 50%;
    border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.15);
    cursor: pointer; transition: transform 0.1s;
  }
  .mep-color-swatch:hover { transform: scale(1.15); }
  /* Natiivi värinvalitsin (2026-05-07): pyöreä, kuten swatch — mutta varmasti tallentaa hex */
  .mep-color-input {
    width: 28px; height: 28px; border-radius: 50%;
    border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.15);
    cursor: pointer; padding: 0; background: transparent;
    transition: transform 0.1s;
  }
  .mep-color-input:hover { transform: scale(1.10); }
  .mep-color-input::-webkit-color-swatch-wrapper { padding: 0; border-radius: 50%; }
  .mep-color-input::-webkit-color-swatch { border: 0; border-radius: 50%; }
  .mep-color-input::-moz-color-swatch { border: 0; border-radius: 50%; }
  .mep-actions { display: flex; gap: 4px; padding-top: 4px; border-top: 1px dashed #FCD34D; }
  .mep-actions button {
    flex: 1; padding: 5px 6px; font-size: 10px; font-weight: 600;
    border: 1px solid #FCD34D; border-radius: 5px; cursor: pointer; background: var(--panel);
    color: #92400E; font-family: inherit;
  }
  .mep-actions button:hover { background: #FCD34D; color: #1f1f1f; }
  .mep-save-btn { background: #16A34A !important; color: #fff !important; border-color: #16A34A !important; }
  .mep-save-btn:hover { background: #0E7C2E !important; color: #fff !important; }
  .mep-delete-all-btn:hover { background: #dc2626 !important; color: #fff !important; border-color: #dc2626 !important; }
  .marker-singles-head {
    margin-top: 6px; padding-top: 6px; border-top: 1px dashed #FCD34D;
    font-size: 10px; color: #92400E; font-weight: 600;
  }
  .marker-singles-list { max-height: 180px; overflow-y: auto; padding-right: 2px; }
  .marker-single-item {
    display: flex; align-items: center; gap: 6px; padding: 2px 4px;
    font-size: 10px; border-radius: 3px;
  }
  .marker-single-item:hover { background: rgba(252, 211, 77, 0.20); }
  .marker-single-item .spacer { flex: 1; }
  .marker-single-del {
    background: none; border: 0; color: var(--text-muted); cursor: pointer;
    font-size: 12px; padding: 1px 4px; border-radius: 3px;
  }
  .marker-single-del:hover { color: #dc2626; background: #fee2e2; }
  /* Marker shape buttons in toolbar */
  #dt-shape-wrap { display: none; align-items: center; gap: 2px; border-left: 1px solid var(--border); padding-left: 6px; margin-left: 2px; }
  .dt-shape-btn { background: transparent; border: 1px solid transparent; border-radius: 3px; padding: 2px 5px; font-size: 13px; cursor: pointer; }
  .dt-shape-btn:hover { background: var(--bark-light); border-color: var(--border); }
  .dt-shape-btn.active { background: rgba(127,168,106,0.15); border-color: var(--blue); }
  /* Draw color swatch */
  #dt-color-swatch { width: 18px; height: 18px; border-radius: var(--radius-sm); border: 1.5px solid var(--border); cursor: pointer; display: none; flex-shrink: 0; vertical-align: middle; }
  /* 2026-05-24o: Pikku popupit (zone/marker/measure/stamp/tray/comment) yhtenäiseen
     moderniin tyyliin — pehmeämpi varjostus, isompi radius, oranssi focus. */
  #zone-name-popup,
  #marker-name-popup,
  #measure-confirm-popup,
  #stamp-name-popup,
  #tray-name-popup {
    position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%);
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 11px;
    box-shadow: 0 12px 36px rgba(15,31,58,0.15), 0 2px 6px rgba(15,31,58,0.08);
    padding: 16px 20px;
    z-index: 900;
    display: none;
    flex-direction: column;
    gap: 10px;
    font-family: inherit;
  }
  #zone-name-popup { min-width: 280px; }
  #marker-name-popup { min-width: 280px; }
  #measure-confirm-popup { min-width: 340px; gap: 8px; }
  #stamp-name-popup { min-width: 320px; gap: 9px; }
  #tray-name-popup { min-width: 340px; gap: 9px; }
  #zone-name-popup.show,
  #marker-name-popup.show,
  #measure-confirm-popup.show,
  #stamp-name-popup.show,
  #tray-name-popup.show { display: flex; animation: pop-in 0.18s cubic-bezier(0.16, 1, 0.3, 1); }
  @keyframes pop-in {
    from { opacity: 0; transform: translate(-50%, -50%) scale(0.96); }
    to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  }
  /* Otsikko — yhtenäinen tyyli */
  .znp-title {
    font-size: 13.5px; font-weight: 700; margin: 0 0 2px;
    color: var(--text); letter-spacing: -0.01em;
  }
  /* Inputs — oranssi focus, isompi padding */
  #zone-name-popup input,
  #marker-name-popup input,
  #measure-confirm-popup input,
  #stamp-name-popup input,
  #tray-name-popup input,
  #tray-name-popup select {
    padding: 7px 10px; font-size: 13px;
    border: 1px solid var(--border); border-radius: var(--radius-md);
    font-family: inherit; outline: none;
    background: var(--panel);
    transition: border-color 0.12s, box-shadow 0.12s;
  }
  #zone-name-popup input:focus,
  #marker-name-popup input:focus,
  #measure-confirm-popup input:focus,
  #stamp-name-popup input:focus,
  #tray-name-popup input:focus,
  #tray-name-popup select:focus {
    border-color: var(--blue);
    box-shadow: 0 0 0 2px rgba(15,31,58,0.15);
  }
  /* Comment text input popup — pieni inline-popup */
  #comment-input-popup {
    position: fixed; background: var(--panel);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    box-shadow: 0 8px 24px rgba(15,31,58,0.15), 0 2px 6px rgba(15,31,58,0.08);
    padding: 10px 12px;
    z-index: 900; display: none;
    gap: 7px; flex-direction: column; min-width: 220px;
  }
  #comment-input-popup.show { display: flex; }
  #comment-input-field {
    border: 1px solid var(--border); border-radius: var(--radius-md);
    padding: 6px 9px; font-size: 12.5px; font-family: inherit; outline: none;
    transition: border-color 0.12s, box-shadow 0.12s;
  }
  #comment-input-field:focus {
    border-color: var(--blue);
    box-shadow: 0 0 0 2px rgba(15,31,58,0.15);
  }
  /* 2026-05-17: #new-product-popup-modaali POISTETTU — korvasi inline-pending-rivi */
  /* Checklist */
  .cl-item { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 12px; }
  .cl-item input[type="checkbox"] { accent-color: var(--blue); cursor: pointer; flex-shrink: 0; }
  .cl-count { font-weight: 700; color: var(--blue); }

  /* Hover-tooltip osumille — näyttää symbolin tiedot kun hiiri liikkuu päällä */
  #match-tooltip {
    display: none;
    position: fixed;
    z-index: 100;
    background: var(--navy);
    color: #fff;
    padding: 6px 10px;
    border-radius: 5px;
    font-size: 12px;
    font-weight: 600;
    pointer-events: none;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    white-space: nowrap;
  }
  #match-tooltip .mt-label {
    font-size: 14px; font-weight: 800; margin-bottom: 2px;
  }
  #match-tooltip .mt-meta {
    font-size: 11px; color: rgba(255,255,255,0.75); font-weight: 400;
  }
  #match-tooltip .mt-color-dot {
    display: inline-block; width: 10px; height: 10px; border-radius: 50%;
    margin-right: 6px; vertical-align: middle;
  }
  /* Pikanäppäin-vihjeet napeissa — Apple-tyyliset glassmorphic kbd-merkit */
  button kbd {
    display: inline-block; margin-left: 6px;
    background: rgba(255,255,255,0.22); color: inherit;
    border: 1px solid rgba(255,255,255,0.32);
    border-radius: var(--radius-sm);
    padding: 1px 5px; font-size: 9.5px; font-family: var(--mono);
    font-weight: 600; letter-spacing: 0.02em;
    line-height: 1.3; vertical-align: middle;
    backdrop-filter: blur(2px);
  }
  button.secondary kbd {
    background: rgba(255,255,255,0.10);
    border-color: rgba(255,255,255,0.22);
  }
  /* Vaalea-pohjaisten nappien kbd (esim. tiedostonimet) */
  .rb-btn kbd, .rb-icon-btn kbd, .dt-btn kbd {
    background: rgba(0,0,0,0.05);
    border-color: rgba(0,0,0,0.12);
    color: var(--text-muted);
  }
  body.space-held #viewport-wrap::before {
    content: 'TEKSTIMERKKI-LINKITYS — klikkaa merkkejä lisätäksesi linkitetyksi tekstiksi aktiivisen tuotteen alle';
    position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
    background: var(--blue); color: #fff; padding: 4px 12px;
    border-radius: var(--radius-sm); font-weight: 600; font-size: 11px; z-index: 100;
    pointer-events: none;
  }
  #text-overlay rect.text-glyph {
    fill: rgba(15,31,58,0.10);
    stroke: var(--blue);
    stroke-width: 0.5;
    pointer-events: auto;
    cursor: pointer;
  }
  #text-overlay rect.text-glyph:hover {
    fill: rgba(15,31,58,0.45);
    stroke-width: 1.5;
  }
  .linked-text-chip {
    background: var(--blue); color: #fff;
    padding: 2px 6px; border-radius: 3px;
    font-size: 11px; font-weight: 700;
    cursor: pointer;
    user-select: none;
  }
  .linked-text-chip:hover { background: #c0521c; }
  .link-hint {
    font-size: 10px; color: #999;
    margin-left: auto;
    font-style: italic;
  }

  /* Pending-row CSS poistettu (2026-05-05) — modal-bg on ainoa muokkausikkuna. */

  /* Match results */
  .match-section {
    padding: 8px 10px;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
  }
  .match-section-head {
    display: flex; align-items: center; gap: 6px;
    margin-bottom: 6px;
  }
  .match-section-head h2 { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: #999; margin: 0; flex: 1; }
  .match-section-head button {
    padding: 3px 9px; border: 1px solid var(--border);
    background: var(--panel); border-radius: var(--radius-sm); cursor: pointer;
    font-family: inherit; font-size: 12px;
  }
  .match-section-head button:hover { background: #f0f8ff; }
  .vis-row { display: flex; gap: 12px; font-size: 12px; margin-bottom: 6px; }
  .stats { background: #f6f4f0; padding: 7px 9px; border-radius: var(--radius-sm); font-size: 12px; line-height: 1.6; }

  /* Admin */
  .admin-row {
    display: flex; gap: 4px;
    padding: 6px 8px;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
  }
  .admin-row button {
    flex: 1; padding: 4px 6px;
    border: 1px solid var(--border); background: var(--panel);
    border-radius: var(--radius-sm); cursor: pointer;
    font-family: inherit; font-size: 11px; color: #666;
  }
  .admin-row button:hover { background: #f6f4f0; }
  .admin-row button.danger { color: #c00; }
  .admin-row button.danger:hover { background: #fff0f0; }

  /* Modal */
  /* ── Tuotehaku autocomplete ─────────────────────────────────────────────── */
  .autocomplete-list {
    position: absolute; bottom: 100%; left: 0; right: 0;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px 8px 0 0;
    box-shadow: 0 -8px 24px rgba(0,0,0,0.18);
    max-height: 280px; overflow-y: auto;
    display: none; z-index: 1100;
    margin-bottom: 2px;
    min-width: 280px;
  }
  /* Alas-aukeava variantti (esim. modaalin yläpalkin input) */
  .autocomplete-list-down {
    bottom: auto; top: 100%;
    border-radius: 0 0 8px 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    margin-top: 2px; margin-bottom: 0;
  }
  .autocomplete-list.show { display: block; }
  .ac-item {
    padding: 7px 12px; cursor: pointer;
    border-bottom: 1px solid #f0ece2;
    display: flex; align-items: baseline; gap: 8px;
    font-size: 12px;
  }
  .ac-item:last-child { border-bottom: 0; }
  .ac-item.ac-existing {
    background: linear-gradient(90deg, rgba(15,158,213,0.10) 0%, transparent 100%);
    border-left: 0;
    padding-left: 7px;
  }
  .ac-item.ac-existing .ac-code { color: var(--text); font-weight: 700; }
  .ac-item.ac-existing .ac-desc { color: #888; font-style: italic; font-size: 11px; }
  .ac-existing-badge { color: var(--blue); margin-right: 5px; font-size: 10px; }
  /* Rekisteri-tila-merkit: 🟢/🟡/⚪ — kertoo onko hakukoodi rekisterissä + tuotenrot OK */
  .ac-rek-badge { display:inline-block; width: 8px; font-size: 12px; line-height: 1; margin-right: 4px; flex-shrink: 0; }
  .ac-rek-ok { color: #22c55e; }      /* vihreä — toimii viennissä */
  .ac-rek-empty { color: #eab308; }   /* keltainen — rekisterissä mutta tuotenrot puuttuvat */
  .ac-rek-none { color: #cbd5e1; }    /* harmaa — ei rekisterissä */
  /* 2026-05-16: Sigi-modaalin label-statusrivi (näytetään input:n alla, fuzzy-suoja) */
  .mls { display: none; padding: 6px 12px; font-size: 12px; line-height: 1.4;
    border-bottom: 1px solid var(--border); background: var(--bg); }
  .mls.show { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .mls .mls-icon { font-size: 14px; flex-shrink: 0; }
  .mls .mls-text { color: var(--text); }
  .mls.ok { background: #F0FDF4; color: #166534; }
  .mls.empty { background: #FFFBEB; color: #92400E; }
  .mls.new { background: #F1F5F9; color: #475569; }
  .mls .mls-suggest-btn { margin-left: auto; padding: 3px 10px; border-radius: var(--radius-sm);
    border: 1px solid currentColor; background: rgba(255,255,255,0.6); cursor: pointer;
    font-size: 11px; font-weight: 600; color: inherit; }
  .mls .mls-suggest-btn:hover { background: rgba(255,255,255,0.95); }
  .ac-item:hover, .ac-item.ac-selected {
    background: var(--bark-light);
  }
  .ac-item .ac-code {
    font-family: var(--mono); font-weight: 700;
    color: var(--blue); flex-shrink: 0;
    min-width: 70px;
  }
  .ac-item .ac-desc {
    color: var(--text-muted); font-size: 11px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .ac-item mark {
    background: rgba(15,31,58,0.25); color: inherit;
    padding: 0 2px; border-radius: 2px;
  }
  .ac-empty {
    padding: 10px 12px; color: var(--text-muted);
    font-size: 11px; font-style: italic;
  }

  /* 2026-07-05 (B3): worklist-rivin valintaruutu kevennetty — ei saa kilpailla
     huomiosta perhetoggle/otsikkorivin kanssa. Koko+opasiteetti inline (leveys/
     korkeus vaihtelee koodikohdassa), hover-tummennus vain täällä (:hover ei
     onnistu inline style="":llä). */
  .wl-pick { opacity: 0.7; transition: opacity 0.12s; }
  .wl-pick:hover, .wl-pick:focus-visible { opacity: 1; }

  /* ───────────────────────────────────────────────────────────────────────
     APPLE-TYYLINEN VEKTORIVALINTAMODAALI
     Frosted glass · pehmeät reunat · kerrosvarjot · hienovaraiset siirtymät
     ─────────────────────────────────────────────────────────────────────── */
  #modal-bg {
    display: none; position: fixed; inset: 0;
    background: rgba(15,31,58,0.55);
    backdrop-filter: blur(8px) saturate(140%);
    -webkit-backdrop-filter: blur(8px) saturate(140%);
    /* 2026-05-08: nostettu 1000 → 1700 jotta vektorimuokkaus aukeaa AINA muiden
       modaalien (Mallit 1500, kirjasto 1600, gallery 1500, popup 1500) päälle.
       Muutoin esim. Mallit-modaalin thumb-klik avasi modal-bg:n piiloon Mallit:n
       taakse (käyttäjä näki vain Mallit-näkymän, vaikka modaali oli "auki").
       2026-07-07: 1700 → 1950 (käyttäjä: "Tarkista-modaali aukeaa taustalle"): jäi
       kontekstivalikon (1850) / coverage (1750) / reittipopupin (1900) taakse. Nyt
       niiden päällä, mutta kirjaston (2000) alla → kirjasto avautuu yhä editorin päälle. */
    z-index: 1950; align-items: center; justify-content: center;
    padding: 24px;
    animation: modal-fade-in 0.2s ease-out;
  }
  #modal-bg.show { display: flex; }
  /* 2026-06-05 Countfire: TELAKOITU tila (varianttimuokkaus) — modaali oikealle piirustuksen
     päälle, EI himmennystä/blokkausta → vasen paneeli (variantti-thumbit) pysyy elävänä ja
     klikattavana (pointer-events:none läpäisee tyhjän overlayn, kortti itse on auto). */
  #modal-bg.docked { background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none;
    pointer-events: none; justify-content: flex-end; align-items: stretch; padding: 0; animation: none; }
  #modal-bg.docked #modal { pointer-events: auto; width: 520px; max-width: 46vw; height: 100%;
    max-height: none; border-radius: 0; border-left: 1px solid var(--border);
    box-shadow: -12px 0 32px rgba(0,0,0,0.18); animation: none; }
  @keyframes modal-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
  }
  #modal {
    background: var(--panel); border-radius: 14px;
    width: 100%; height: 100%; max-width: 1400px; max-height: 900px;
    display: flex; flex-direction: column;
    overflow: hidden;
    box-shadow:
      0 1px 2px rgba(0,0,0,0.08),
      0 8px 24px rgba(0,0,0,0.12),
      0 24px 64px rgba(0,0,0,0.24);
    animation: modal-pop 0.22s cubic-bezier(0.16, 1, 0.3, 1);
  }
  @keyframes modal-pop {
    from { opacity: 0; transform: scale(0.96) translateY(8px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
  }

  /* Otsikkorivi — tumma, kompakti, tasapainoinen */
  #modal-head {
    padding: 12px 20px;
    /* 2026-06-05 v2: sama navy kuin #tool-rail (käyttäjä: "sininen yläosa kuten rail") */
    background: #0F1F3A;
    color: #fff;
    display: flex; align-items: center; gap: 10px; flex-shrink: 0; flex-wrap: wrap; row-gap: 8px;
    border-bottom: 1px solid #21314d;
  }
  /* ═══ 2026-06-06: MODAALIEN YHTENÄINEN BRAND-NAVY HEADER (#0F1F3A, sama kuin #modal-head).
     Additiivinen per-#id-yliajo joka kohdistaa VAIN header-riviin (panel-divin 1. lapsi-div) —
     ei kosketa inline-mittoihin eikä bodyyn. Korjaa: Library white-on-white, Gallery tumma-tummalla,
     meas-edit/stamp/quantities/estimate vaalea gradient, copy-sys/laskenta/batch/models slate≠brand. */
  #meas-edit-modal > div:first-child,
  #stamp-picker-modal > div:first-child,
  #library-modal > div:first-child,
  #gallery-modal > div:first-child,
  #copy-sys-modal > div:first-child,
  #quantities-modal > div:first-child,
  #estimate-modal > div:first-child,
  #est-settings-bg > div > div:first-child,
  #est-remap-picker-bg > div > div:first-child,
  #est-add-product-bg > div > div:first-child,
  #laskenta-export-modal > div:first-child,
  #batch-summary-modal > div:first-child,
  #models-modal > div:first-child {
    background: #0F1F3A !important;
    border-bottom: 1px solid #21314d !important;
    color: #fff !important;
  }
  /* otsikot valkoisiksi (kumoaa tummat inline-värit, mm. gallery var(--blue), quantities #0F1F3A) */
  #meas-edit-modal > div:first-child h2,    #meas-edit-modal > div:first-child h3,
  #stamp-picker-modal > div:first-child h2, #stamp-picker-modal > div:first-child h3,
  #library-modal > div:first-child h2,
  #gallery-modal > div:first-child h2,
  #copy-sys-modal > div:first-child h2,
  #quantities-modal > div:first-child h2,
  #estimate-modal > div:first-child h2,
  #est-settings-bg > div > div:first-child h3,
  #est-remap-picker-bg > div > div:first-child h2, #est-remap-picker-bg > div > div:first-child h3,
  #est-add-product-bg > div > div:first-child h2, #est-add-product-bg > div > div:first-child h3,
  #laskenta-export-modal > div:first-child h2,
  #batch-summary-modal > div:first-child h2,
  #models-modal > div:first-child h2 { color: #fff !important; }
  /* header-ikonit (svg stroke=currentColor) valkoisiksi + suorat span/label-lapset himmeä-valkoisiksi (meta/summary) */
  #meas-edit-modal > div:first-child svg, #stamp-picker-modal > div:first-child svg,
  #library-modal > div:first-child svg, #gallery-modal > div:first-child svg,
  #copy-sys-modal > div:first-child svg, #quantities-modal > div:first-child svg,
  #estimate-modal > div:first-child svg, #models-modal > div:first-child svg,
  #laskenta-export-modal > div:first-child svg,
  #est-settings-bg > div > div:first-child svg { color: #fff !important; }
  #meas-edit-modal > div:first-child > span, #stamp-picker-modal > div:first-child > span,
  #library-modal > div:first-child > span, #gallery-modal > div:first-child > span,
  #copy-sys-modal > div:first-child > span, #quantities-modal > div:first-child > span,
  #estimate-modal > div:first-child > span, #models-modal > div:first-child > span,
  #laskenta-export-modal > div:first-child > span,
  #est-settings-bg > div > div:first-child > span { color: rgba(255,255,255,0.78) !important; }
  /* header-napit + inputit lasimaisiksi tummalla pohjalla (kumoaa vaaleat napit/reunat #CBD5E1) */
  #meas-edit-modal > div:first-child button,    #meas-edit-modal > div:first-child input,
  #stamp-picker-modal > div:first-child button, #stamp-picker-modal > div:first-child input,
  #library-modal > div:first-child button,      #library-modal > div:first-child input, #library-modal > div:first-child select,
  #gallery-modal > div:first-child button,      #gallery-modal > div:first-child select,
  #copy-sys-modal > div:first-child button,
  #quantities-modal > div:first-child button,   #quantities-modal > div:first-child input,
  #estimate-modal > div:first-child button:not(.modal-action-primary),
  #est-settings-bg > div > div:first-child button,
  #est-remap-picker-bg > div > div:first-child button,
  #est-add-product-bg > div > div:first-child button,
  #laskenta-export-modal > div:first-child button,
  #batch-summary-modal > div:first-child button,
  #models-modal > div:first-child button,       #models-modal > div:first-child input {
    background: rgba(255,255,255,0.12) !important; color: #fff !important;
    border: 1px solid rgba(255,255,255,0.22) !important;
  }
  #meas-edit-modal > div:first-child button:hover, #stamp-picker-modal > div:first-child button:hover,
  #library-modal > div:first-child button:hover,  #gallery-modal > div:first-child button:hover,
  #copy-sys-modal > div:first-child button:hover, #quantities-modal > div:first-child button:hover,
  #estimate-modal > div:first-child button:not(.modal-action-primary):hover,
  #laskenta-export-modal > div:first-child button:hover, #batch-summary-modal > div:first-child button:hover,
  #models-modal > div:first-child button:hover { background: rgba(255,255,255,0.22) !important; }
  #library-modal > div:first-child input::placeholder { color: rgba(255,255,255,0.6) !important; }
  /* 2026-06-27: #rekisteri-modal teema-CSS poistettu (paste-modaali poistettu). */
  /* ═══ 2026-06-06: Teemattu dialogi (uiConfirm/uiAlert/uiPrompt) — korvaa natiivit selaimen confirm/alert/prompt ═══ */
  #ui-dialog-bg { display:none; position:fixed; inset:0; background:rgba(15,31,58,0.45); backdrop-filter:blur(3px); z-index:13000; align-items:center; justify-content:center; }
  #ui-dialog-bg.show { display:flex; }
  #ui-dialog { width:430px; max-width:92%; background:var(--panel); border-radius:14px; box-shadow:0 24px 64px rgba(0,0,0,0.34); overflow:hidden; display:flex; flex-direction:column; animation:ui-dialog-in .14s ease; }
  @keyframes ui-dialog-in { from { opacity:0; transform:translateY(8px) scale(.985); } to { opacity:1; transform:none; } }
  #ui-dialog-head { background:#0F1F3A; color:#fff; padding:12px 18px; font-size:14px; font-weight:600; letter-spacing:-0.01em; display:flex; align-items:center; gap:8px; flex-shrink:0; }
  #ui-dialog-body { padding:18px; font-size:13.5px; color:var(--text); line-height:1.5; max-height:60vh; overflow-y:auto; }
  #ui-dialog-msg { margin:0; white-space:pre-wrap; word-break:break-word; }
  #ui-dialog-input { width:100%; margin-top:12px; padding:8px 10px; border:1px solid var(--border); border-radius:7px; font-size:13px; font-family:inherit; box-sizing:border-box; }
  #ui-dialog-input:focus { outline:none; border-color:var(--blue); }
  #ui-dialog-foot { display:flex; justify-content:flex-end; gap:8px; padding:12px 18px; background:var(--bg); border-top:1px solid var(--border); flex-shrink:0; }
  #ui-dialog-foot button { padding:7px 16px; border-radius:7px; font-size:13px; font-weight:600; cursor:pointer; font-family:inherit; border:1px solid var(--border); }
  #ui-dialog-cancel { background:var(--panel); color:var(--text); }
  #ui-dialog-cancel:hover { background:var(--btn-sec-bg); }
  #ui-dialog-ok { background:var(--btn-bg); color:var(--btn-fg); border-color:var(--btn-bg); }
  #ui-dialog-ok:hover { background:var(--btn-bg-hover); }
  #ui-dialog.danger #ui-dialog-ok { background:#dc2626; color:#fff; border-color:#dc2626; }
  #ui-dialog.danger #ui-dialog-ok:hover { background:#b91c1c; }
  #modal-head h2 {
    margin: 0; font-size: 14px; font-weight: 600;
    letter-spacing: -0.01em; color: #fff;
  }
  #modal-head .spacer { flex: 1; }
  #modal-head .mh-name { position: relative; }
  /* 2026-06-05 v2: nimi = otsikko; väri + Kaikki rotaatiot + Peruuta + Valmis navy-headerissa */
  #modal-head .mh-name input { font-size: 14px; font-weight: 600; min-width: 210px; }
  #modal-head .mh-color { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
  #modal-head .mh-color-lbl { font-size: 11px; font-weight: 600; color: rgba(255,255,255,0.72); }
  #modal-head #modal-cancel { background: rgba(255,255,255,0.10); color: #fff; border: 1px solid rgba(255,255,255,0.22); padding: 7px 14px; border-radius: 8px; cursor: pointer; font-family: inherit; font-size: 13px; font-weight: 600; }
  #modal-head #modal-cancel:hover { background: rgba(255,255,255,0.18); }
  #modal-head #modal-save { background: var(--btn-bg); color: var(--btn-fg); border: 1px solid var(--btn-bg); padding: 7px 18px; border-radius: 8px; cursor: pointer; font-family: inherit; font-size: 13px; font-weight: 700; }
  #modal-head #modal-save:hover { background: var(--btn-bg-hover); }
  /* 2026-07-07: klusterimuokkauksen Hylkää-nappi (näkyy vain thumbnaili-editorissa) */
  #modal-head #modal-reject { background: rgba(255,255,255,0.08); color: #ffd7d3; border: 1px solid rgba(255,120,110,0.45); padding: 7px 14px; border-radius: 8px; cursor: pointer; font-family: inherit; font-size: 13px; font-weight: 600; }
  #modal-head #modal-reject:hover { background: rgba(220,60,50,0.28); color: #fff; }
  /* 2026-07-07: kosketuseleet omistaa gesture-handler (app-54) — estä selaimen natiivi pan/zoom SVG-alueella (iPad) */
  #modal-svg { touch-action: none; }
  /* 2026-07-07: klusterimuokkauksen thumbnaili on klikattava (avaa editorin) */
  .wl-thumb.wl-thumb-edit { cursor: pointer; border-radius: 8px; transition: background .12s, box-shadow .12s; position: relative; }
  .wl-thumb.wl-thumb-edit:hover { background: var(--gf-field,#f0f4ff); box-shadow: 0 0 0 2px var(--btn-bg) inset; }
  /* 2026-07-07: iPad/kapea ruutu — pienennä reunusta jotta piirtoalue on isompi + estä ylivuoto */
  @media (max-width: 1024px) {
    #modal-bg { padding: 10px; }
    #modal { max-height: none; height: 100%; }
    #modal-head { padding: 10px 12px; gap: 8px; }
    #modal-toolrow { padding: 8px 12px; }
  }
  /* 2026-06-05 Countfire modal chrome: tilastorivi, työkalurivi, varianttirivi */
  #modal-x { margin-left: 2px; width: 30px; height: 30px; flex-shrink: 0; display: flex;
    align-items: center; justify-content: center; background: rgba(255,255,255,0.10);
    border: 1px solid rgba(255,255,255,0.18); border-radius: 7px; color: #fff; font-size: 14px;
    cursor: pointer; font-family: inherit; line-height: 1; transition: background .12s; }
  #modal-x:hover { background: rgba(255,255,255,0.22); }
  #modal-stats { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; row-gap: 4px;
    padding: 10px 20px; flex-shrink: 0; background: var(--bg); border-bottom: 1px solid var(--border); }
  #modal-stats .ms-stat { display: flex; align-items: baseline; gap: 7px; }
  #modal-stats .ms-lbl { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); }
  #modal-stats .ms-stat b { font-family: var(--mono); font-size: 16px; font-weight: 800; color: var(--text); }
  #modal-stats .ms-dim { opacity: .5; }
  #modal-tabs { display: flex; gap: 4px; padding: 8px 20px 0; flex-shrink: 0; background: var(--bg); border-bottom: 1px solid var(--border); }
  #modal-tabs .modal-tab { appearance: none; border: 0; background: transparent; font-family: inherit; font-size: 12.5px; font-weight: 600; color: var(--text-muted); padding: 8px 12px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
  #modal-tabs .modal-tab:hover { color: var(--text); }
  #modal-tabs .modal-tab.active { color: var(--text); border-bottom-color: var(--blue); }
  /* 2026-08-01: rivi siirretty modaalin alaosaan (SVG:n alle) → erotin yläreunaan */
  #modal-toolrow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 10px 20px; flex-shrink: 0; background: var(--panel); border-top: 1px solid var(--border); }
  #modal-toolrow .modal-zoom-ctl { margin-left: auto; }
  #modal-toolrow .mtr-sep { width: 1px; align-self: stretch; min-height: 22px; background: var(--border); margin: 0 4px; }
  #modal-toolrow .mtr-check { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--text); cursor: pointer; padding: 5px 9px; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); }
  #modal-toolrow .mtr-check input { margin: 0; cursor: pointer; }
  #modal-toolrow .mtr-color { display: inline-flex; align-items: center; gap: 7px; }
  #modal-toolrow .mtr-lbl { font-size: 12px; font-weight: 600; color: var(--text-muted); }
  /* Vektorivalinnan toissijaiset napit: vaaleat chipit.
     KORJAUS (käyttäjäpalaute): ilman omaa sääntöä nämä saivat selaimen TUMMAN natiivinapin
     ("tummia oudon värisiä"). Yhtenäinen vaalea chip kuten viereinen .mtr-check, navy-hover. */
  #modal-toolrow button {
    font-family: inherit; font-size: 12px; font-weight: 600; line-height: 1;
    color: var(--text); background: var(--panel);
    border: 1px solid var(--border); border-radius: 7px;
    padding: 6px 11px; cursor: pointer;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
  }
  #modal-toolrow button:hover {
    background: var(--panel-soft); border-color: var(--blue); color: var(--blue);
  }
  #modal-toolrow button:active { transform: translateY(1px); }
  /* "Tyhjennä" on poistava toiminto → punainen affordanssi vasta hoverissa (ei räikeä oletuksena) */
  #modal-toolrow button#modal-clear:hover {
    border-color: var(--danger); color: var(--danger); background: var(--danger-soft);
  }
  #modal-variant-strip { display: flex; align-items: center; gap: 8px; padding: 9px 20px; flex-shrink: 0; background: var(--bg); border-bottom: 1px solid var(--border); overflow-x: auto; }
  #modal-variant-strip .mvs-item { flex: 0 0 auto; width: 54px; height: 54px; padding: 3px; border: 2px solid var(--border); border-radius: 9px; background: var(--panel); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: border-color .12s, box-shadow .12s; }
  #modal-variant-strip .mvs-item:hover { border-color: var(--blue); }
  #modal-variant-strip .mvs-item.active { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(30,47,74,0.18); }
  #modal-variant-strip .mvs-item img { max-width: 100%; max-height: 100%; object-fit: contain; pointer-events: none; }
  #modal-foot .mfoot-hint { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; font-size: 11.5px; color: var(--text-muted); }
  #modal-foot .mfoot-hint .mfh { display: inline-flex; align-items: center; gap: 5px; }
  #modal-foot .mfoot-hint .mfh svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--text-muted); }
  #modal-foot .mfoot-hint .mfh em { font-style: normal; font-weight: 700; }

  /* Input — frosted glass, focus-rengasta */
  #modal-head input {
    background: rgba(255,255,255,0.96); color: var(--text);
    border: 1px solid transparent;
    padding: 7px 12px; border-radius: 7px;
    font-size: 13px; font-weight: 500; width: 200px;
    font-family: inherit;
    transition: box-shadow 0.15s, border-color 0.15s;
  }
  #modal-head input::placeholder { color: rgba(0,0,0,0.4); font-weight: 400; }
  #modal-head input:focus {
    outline: none;
    border-color: var(--blue);
    box-shadow: 0 0 0 3px rgba(15,31,58,0.25);
  }

  /* Primary — Tallenna (oranssi accent) */
  #modal-head button {
    background: var(--blue); color: #fff;
    border: 0; padding: 7px 14px; border-radius: 7px;
    cursor: pointer; font-weight: 600; font-family: inherit;
    font-size: 12px; letter-spacing: 0.01em;
    transition: transform 0.1s, box-shadow 0.15s, filter 0.15s;
    box-shadow: 0 1px 0 rgba(0,0,0,0.15) inset, 0 1px 2px rgba(0,0,0,0.18);
  }
  #modal-head button:hover { filter: brightness(1.08); transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0,0,0,0.22); }
  #modal-head button:active { transform: translateY(0); filter: brightness(0.95); }

  /* Secondary napit — frosted, hienovarainen reuna */
  #modal-head button.secondary {
    background: rgba(255,255,255,0.10);
    border: 1px solid rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.92);
    box-shadow: none;
    backdrop-filter: blur(4px);
  }
  #modal-head button.secondary:hover {
    background: rgba(255,255,255,0.20);
    border-color: rgba(255,255,255,0.30);
  }

  /* Color swatch — pyöreä, hienosti reunustettu */
  #modal-head #modal-color-swatch {
    width: 28px; height: 28px; border-radius: 50%;
    cursor: pointer; flex-shrink: 0;
    border: 2px solid rgba(255,255,255,0.85);
    box-shadow: 0 0 0 1px rgba(0,0,0,0.3), 0 2px 4px rgba(0,0,0,0.2);
    transition: transform 0.15s, box-shadow 0.15s;
  }
  #modal-head #modal-color-swatch:hover {
    transform: scale(1.1);
    box-shadow: 0 0 0 1px rgba(0,0,0,0.3), 0 4px 12px rgba(0,0,0,0.3);
  }

  /* Hint-teksti otsikossa */
  #modal-hint {
    font-size: 11px; opacity: 0.6;
    font-family: var(--mono); letter-spacing: 0.02em;
  }

  /* Vektorivalinta-alue — vaalea, kalibroituihen taustoihin */
  #modal-body {
    flex: 1; overflow: auto;
    background: linear-gradient(180deg, #faf8f3 0%, #f5f2eb 100%);
    padding: 28px; display: flex;
    align-items: flex-start; justify-content: center;
    user-select: none; -webkit-user-select: none;
    /* 2026-05-29: oma hiusristikko-kursori (tumma ydin + valkoinen reunus) — näkyy
       vaalealla taustalla VAIKKA käyttäjän Windows-kursoriväri olisi valkoinen.
       Korvasi pelkän 'crosshair'-kursorin, jonka OS renderöi väriskeeman mukaan
       (valkoinen kursori katosi vaaleaan valintakenttään). Hotspot keskellä (12,12). */
    --vec-cursor: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48ZyBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjxwYXRoIGQ9Ik0xMiAydjdNMTIgMTV2N00yIDEyaDdNMTUgMTJoNyIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjMuNSIvPjxwYXRoIGQ9Ik0xMiAydjdNMTIgMTV2N00yIDEyaDdNMTUgMTJoNyIgc3Ryb2tlPSIjMTExMTExIiBzdHJva2Utd2lkdGg9IjEuNSIvPjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEiIGZpbGw9IiMxMTExMTEiLz48L2c+PC9zdmc+") 12 12, crosshair;
    cursor: var(--vec-cursor);
  }
  #modal-svg-wrap {
    /* 2026-06-05 Countfire: shakkiruutu-tausta symbolin takana (läpinäkyvä-look) */
    background-color: #fbfaf7;
    background-image:
      linear-gradient(45deg, #ececea 25%, transparent 25%),
      linear-gradient(-45deg, #ececea 25%, transparent 25%),
      linear-gradient(45deg, transparent 75%, #ececea 75%),
      linear-gradient(-45deg, transparent 75%, #ececea 75%);
    background-size: 16px 16px;
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
    border-radius: var(--radius-xl);
    border: 1px solid rgba(0,0,0,0.06);
    box-shadow:
      0 1px 2px rgba(0,0,0,0.05),
      0 4px 12px rgba(0,0,0,0.08);
    padding: 16px;
  }

  /* Vektorit — selvä erottelu valittu/hylätty, smooth animaatiot */
  #modal-svg .vec {
    /* pointer-events: all → vektori klikattava koko bbox-alueelta vaikka fill:none.
       Ennen oli visiblePainted → kapeat tekstirectit (kuten "1") oli vaikea klikata. */
    pointer-events: all; cursor: var(--vec-cursor, crosshair);
    /* 2026-06-10: yhtenäiset valintavärit (--vec-*) — sama kuin inline-paneeli/lasso.
       Valittu = sininen. Transition VAIN opacityyn → ei stroke-välkyntää värin vaihtuessa. */
    fill: none; stroke: var(--vec-sel);
    stroke-width: 5; stroke-linecap: round; stroke-linejoin: round;
    transition: opacity 0.12s ease;
  }
  #modal-svg polygon.vec { fill: var(--vec-sel-fill-soft); }
  #modal-svg polygon.vec.selected { fill: var(--vec-sel-fill); }
  #modal-svg polygon.vec.discarded { fill: none; }
  /* B6: täytetyt polygonit (PDF type='f' / 'fs') näkyvät pohjana tummanharmaina —
     käyttäjä erottaa että alue on alkuperäisessä PDF:ssä TÄYTETTY. Valinta → sininen täyttö. */
  #modal-svg polygon.vec.filled { fill: rgba(26,24,22,0.55); stroke: var(--vec-sel); stroke-width: 1.5; }
  #modal-svg polygon.vec.filled.selected { fill: var(--vec-sel-fill); stroke: var(--vec-sel); stroke-width: 5; }
  #modal-svg polygon.vec.filled.discarded { fill: var(--vec-dis-fill); stroke: var(--vec-dis); stroke-width: 1.5; opacity: 0.85; }
  /* Sama curve/line jotka muodostavat fill-polun (renderöityy <path>:na, ei polygonina) */
  #modal-svg path.vec.filled { fill: rgba(26,24,22,0.55); stroke: var(--vec-sel); stroke-width: 1.5; }
  #modal-svg path.vec.filled.selected { fill: var(--vec-sel-fill); stroke: var(--vec-sel); stroke-width: 5; }
  #modal-svg path.vec.filled.discarded { fill: var(--vec-dis-fill); stroke: var(--vec-dis); stroke-width: 1.5; opacity: 0.85; }
  #modal-svg .vec:hover { stroke: var(--blue); stroke-width: 7; }
  #modal-svg .vec.selected { stroke: var(--vec-sel); stroke-width: 5; opacity: 1; }
  /* 2026-07-02 LISÄTUNNISTE: tunnisteeksi merkityt violetilla (voittaa selected-sinisen).
     Käyttäjäpalaute "ei tiedä onko valittu vai ei" → paksumpi violetti + merkintätilassa
     muut himmennetään → merkityt erottuvat yksiselitteisesti. */
  #modal-svg .vec.float.selected, #modal-svg .vec.float { stroke: #8B5CF6; stroke-width: 6.5; }
  #modal-svg polygon.vec.float.selected { fill: rgba(139, 92, 246, 0.35); }
  #modal-svg.float-mode .vec.selected:not(.float) { opacity: 0.30; }
  #modal-svg.float-mode .vec.discarded { opacity: 0.15; }
  #modal-float-btn.active { background: #8B5CF6 !important; border-color: #8B5CF6 !important; color: #fff !important; }
  /* Lisätunnisteen oma esikatseluikkuna sigivalinnan vieressä (käyttäjäpyyntö 2026-07-02) */
  #modal-svg-wrap { position: relative; }
  #modal-float-panel {
    position: absolute; top: 10px; right: 10px; width: 172px; z-index: 5;
    background: var(--panel, #fff); border: 2px solid #8B5CF6; border-radius: 10px;
    box-shadow: 0 4px 14px rgba(139, 92, 246, 0.25); padding: 8px; display: none;
    font-size: 11px; color: var(--text, #0F1F3A);
  }
  #modal-float-panel.show { display: block; }
  #modal-float-panel .mfp-head {
    font-weight: 700; color: #8B5CF6; display: flex; align-items: center;
    justify-content: space-between; margin-bottom: 4px;
  }
  #modal-float-panel .mfp-count { font-family: ui-monospace, monospace; font-weight: 600; }
  #modal-float-panel svg { display: block; width: 100%; height: 84px; background: #fbfaf7;
    border: 1px solid var(--border, #E8EDF3); border-radius: 6px; }
  #modal-float-panel .mfp-hint { color: var(--text-soft, #5C5C61); margin-top: 4px; line-height: 1.35; }
  #modal-float-panel .mfp-clear {
    margin-top: 6px; width: 100%; font-size: 11px; padding: 4px 6px; cursor: pointer;
    border: 1px solid var(--border, #E8EDF3); border-radius: 6px;
    background: var(--btn-sec-bg, #F1F5F9); color: var(--btn-sec-fg, #475569); font-family: inherit;
  }
  body.theme-dark #modal-float-panel { background: var(--panel); }
  body.theme-dark #modal-float-panel svg { background: #26262b; }
  /* 2026-06-10: hylätty = himmeä punainen (--vec-dis), sama kaikissa valintapinnoissa */
  #modal-svg .vec.discarded { stroke: var(--vec-dis); stroke-width: 2.5; opacity: 1; }
  /* 2026-07-02 zoom: viivapaksuudet + osumapinnat RUUTUPIKSELEINÄ (eivät skaalaudu
     viewBox-zoomissa) → viiva on yhtä helppo osua ja näyttää samalta joka zoomilla. */
  #modal-svg .vec, #modal-svg .modal-crop-ref, #modal-svg #lasso-rect { vector-effect: non-scaling-stroke; }
  /* Käyttäjän alkuperäinen rajaus referenssinä kun valitut viivat ulottuvat sen yli */
  #modal-svg .modal-crop-ref { fill: none; stroke: #94A3B8; stroke-width: 1.5; stroke-dasharray: 5,4; pointer-events: none; }
  .modal-zoom-ctl { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; }
  .modal-zoom-ctl b { font-family: var(--mono); font-size: 11px; min-width: 44px; text-align: center; color: var(--text-soft); }
  .modal-zoom-ctl button { min-width: 28px; padding: 3px 7px; }

  /* Tekstimerkit — katkoviiva-reunalaatikko, sisus läpinäkyvä klikkauksille
     2026-05-20: CSS-fix käyttäjäpalautteen "en pääse valitsemaan oranssin
     laatikon sisältä oikeaa kirjainta" pohjalta. Aiempi rgba-fill peitti
     alla olevat vektori-kirjaimet klikkauksilta vaikka oli melkein näkymätön.
     Nyt: fill:none + pointer-events:visibleStroke → klikit menevät SISUSTASTA
     läpi vektoreille, mutta reuna-katkoviiva on klikattavissa (= text-vec
     valitaan). Reuna selvempi oranssi → käyttäjä erottaa "tämä on PDF-text". */
  #modal-svg .vec.text-vec {
    fill: none;
    pointer-events: visibleStroke;
    stroke: rgba(249, 115, 22, 0.65);
    stroke-width: 1.5;
    stroke-dasharray: 4, 3;
  }
  #modal-svg .vec.text-vec.selected {
    fill: none;
    stroke: #f97316;
    stroke-width: 3;
    stroke-dasharray: none;
    opacity: 1;
  }
  #modal-svg .vec.text-vec.discarded {
    fill: none;
    stroke: #ef9a9a;
    stroke-width: 1.2;
    stroke-dasharray: 3, 3;
    opacity: 0.75;
  }
  #modal-svg .vec.text-vec:hover {
    stroke: #ea580c;
    stroke-width: 3;
    stroke-dasharray: none;
  }
  /* "Hide unsel." -tila: piilota ei-valitut vektorit ja niiden tekstilabelit */
  #modal-svg.hide-unselected .vec.discarded { display: none; }
  #modal-svg.hide-unselected text.modal-text-label[data-discarded="1"] { display: none; }
  /* Aktiivinen-tila napeilla (Hide unsel., ...) */
  #modal-refresh-view.is-active {
    background: #DBE5F0;
    color: #1E2F4A;
    font-weight: 600;
  }

  /* P1 (2026-05-05): NÄKYMÄTÖN PAKSU KOSKETUSRUNKO ohuiden viivojen alle.
     Aiemmin pystyviivat ja muut ohuet viivat olivat vaikea osua siveltimellä —
     SVG-line:n klikkausalue on viivan paksuus (~5px). Hit-elementti laajentaa
     klikkausalueen ~16px → kursorin ei tarvitse osua täsmälleen viivalle. */
  #modal-svg .vec.hit {
    stroke: transparent !important;
    stroke-width: 16 !important;
    stroke-linecap: round !important;
    stroke-linejoin: round !important;
    fill: none !important;
    pointer-events: stroke !important;
    cursor: var(--vec-cursor, crosshair);
    transition: none !important;
    opacity: 1 !important;
  }
  /* Hit-elementti EI muutu valinnan/hoverin mukana — tehtävä on vain tarjota klikkausalue */
  #modal-svg .vec.hit.selected,
  #modal-svg .vec.hit.discarded,
  #modal-svg .vec.hit:hover {
    stroke: transparent !important;
    fill: none !important;
    opacity: 1 !important;
    stroke-width: 16 !important;
  }

  /* Footer — tasapainoinen, tilastolaatikoista visuaalinen rytmi */
  #modal-foot {
    background: linear-gradient(180deg, #f6f4f0 0%, #efece5 100%);
    padding: 10px 20px;
    font-size: 12px;
    border-top: 1px solid rgba(0,0,0,0.06);
    display: flex; gap: 22px; flex-shrink: 0;
    align-items: center;
    color: var(--text-muted);
  }
  #modal-foot b { color: var(--text); font-weight: 700; }
  #modal-foot > span:last-child {
    font-family: var(--mono); font-size: 11px;
    letter-spacing: 0.02em;
  }
  #modal-foot kbd {
    display: inline-block; margin: 0 2px;
    background: var(--panel); color: var(--text);
    border: 1px solid rgba(0,0,0,0.12); border-radius: var(--radius-sm);
    padding: 1px 6px; font-size: 10px; font-family: var(--mono);
    font-weight: 600;
    box-shadow: 0 1px 0 rgba(0,0,0,0.08);
  }
  /* Footerin tilastoryhmä — pisteet piilotettu käyttäjän pyynnöstä 2026-05-05.
     Säilytetty CSS jotta voidaan tarpeen mukaan ottaa takaisin (poista display:none). */
  .mfoot-stat { display: none !important; }
  .mfoot-stat-old-styles {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px;
    background: rgba(255,255,255,0.55);
    border-radius: var(--radius-md);
    border: 1px solid rgba(0,0,0,0.05);
  }
  .mfoot-dot {
    width: 8px; height: 8px; border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.1);
  }
  .mfoot-lbl {
    font-size: 11px; font-weight: 600;
    color: var(--text-muted);
    letter-spacing: 0.01em;
  }
  .mfoot-stat b {
    font-family: var(--mono);
    font-size: 12px; font-weight: 700;
    min-width: 18px; text-align: right;
  }

  /* ── Tiedostopaneeli (vasen) ─────────────────────────────────────────────── */
  #file-panel {
    width: 220px;
    min-width: 140px;
    max-width: 420px;
    background: var(--panel);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    flex-shrink: 0;
    position: relative;
  }
  /* Venytä-kahva oikea reunassa */
  #file-panel-handle {
    position: absolute; right: 0; top: 0; bottom: 0;
    width: 5px; cursor: col-resize; z-index: 20;
    background: transparent; transition: background 0.15s;
  }
  #file-panel-handle:hover { background: var(--blue); opacity: 0.4; }
  #file-list {
    flex: 1; overflow-y: auto; padding: 4px; min-height: 0;
  }
  /* 2026-05-11 KÄYTTÄJÄPYYNTÖ: Järjestelmät PYSTYLISTANA — kaikki aina näkyvissä,
     ei dropdownia. Selkeä silmäys → koko järjestelmä-rakenne. Aktiivinen
     korostettu järjestelmän omalla värillä (vahva reuna + lievä taustaväri). */
  #systems-bar {
    flex-shrink: 0;
    padding: 4px 6px 6px;
    border-bottom: 1px solid var(--border);
    background: var(--panel);
  }
  #systems-bar-header {
    font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em;
    color: var(--text-muted); text-transform: uppercase;
    padding: 4px 4px 6px; user-select: none;
  }
  #systems-list {
    display: flex; flex-direction: column; gap: 3px;
    max-height: 35vh; overflow-y: auto;
  }
  #systems-list .sys-row {
    display: flex; align-items: center; gap: 6px;
    padding: 6px 8px; border-radius: var(--radius-md); cursor: pointer;
    font-size: 12px; color: var(--text);
    border-left: 3px solid transparent;
    background: #fafafa;
    transition: background 0.12s, border-left-color 0.12s;
  }
  #systems-list .sys-row:hover { background: #eef3fb; }
  #systems-list .sys-row.active {
    background: rgba(15, 158, 213, 0.10);
    font-weight: 700;
    color: var(--text);
  }
  #systems-list .sys-row .sys-icon { font-size: 13px; flex-shrink: 0; line-height: 1; }
  #systems-list .sys-row .sys-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #systems-list .sys-row .sys-meta {
    font-size: 9.5px; color: var(--text-muted);
    flex-shrink: 0; font-family: 'JetBrains Mono', ui-monospace, monospace;
  }
  #systems-list .sys-row .sys-actions {
    display: flex; gap: 1px; opacity: 0;
    transition: opacity 0.1s;
  }
  #systems-list .sys-row:hover .sys-actions { opacity: 1; }
  #systems-list .sys-row .sys-act-btn {
    background: none; border: 0; cursor: pointer;
    padding: 2px 5px; font-size: 11px; color: var(--text-muted);
    border-radius: 3px;
  }
  #systems-list .sys-row .sys-act-btn:hover { background: rgba(0,0,0,0.08); color: var(--text); }
  #systems-new-btn {
    width: 100%; margin-top: 5px;
    padding: 6px 8px; background: transparent;
    border: 1px dashed var(--border); border-radius: var(--radius-md);
    cursor: pointer; font-family: inherit; font-size: 11px;
    color: var(--text-muted); font-weight: 600; text-align: center;
    transition: border-color 0.15s, color 0.15s;
  }
  #systems-new-btn:hover { border-color: var(--blue); color: var(--blue); }

  #file-drop-zone {
    flex: 1; display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 8px; padding: 16px; text-align: center;
    border: 2px dashed var(--border); border-radius: var(--radius-lg);
    margin: 8px; cursor: default;
    transition: border-color 0.15s, background 0.15s;
  }
  #file-drop-zone.drag-over { border-color: var(--blue); background: rgba(127,168,106,0.07); }
  #file-drop-zone .dz-icon { font-size: 26px; line-height: 1; }
  #file-drop-zone .dz-text { font-size: 11px; color: var(--text-muted); line-height: 1.5; }
  #file-drop-zone .dz-btn {
    padding: 5px 14px; border-radius: 5px;
    background: var(--blue); color: #fff; border: 0;
    cursor: pointer; font-family: inherit; font-size: 12px; font-weight: 500;
    margin-top: 2px;
  }
  #file-drop-zone .dz-btn:hover { background: var(--leaf-deep); }
  /* 2026-06-07: Tyhjän projektin tuonti-overlay (keskellä piirustusaluetta) + app-laajuinen drag-veil */
  #empty-import {
    position: absolute; inset: 0; z-index: 45;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg); padding: 24px;
  }
  #empty-import .ei-card {
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    text-align: center; padding: 44px 52px; max-width: 440px;
    border: 2px dashed var(--border); border-radius: 18px; background: var(--panel);
    box-shadow: 0 8px 30px rgba(15,31,58,.06);
  }
  #empty-import .ei-icon { font-size: 52px; line-height: 1; }
  #empty-import .ei-title { font-size: 18px; font-weight: 700; color: var(--text); }
  #empty-import .ei-text { font-size: 13.5px; color: var(--text-muted); line-height: 1.6; }
  #empty-import .ei-btn {
    margin-top: 4px; padding: 10px 22px; border: 0; border-radius: 10px;
    background: var(--btn-bg); color: var(--btn-fg); font-weight: 600; font-size: 14px; cursor: pointer;
    transition: background .12s;
  }
  #empty-import .ei-btn:hover { background: var(--btn-bg-hover); }
  #empty-import .ei-hint { font-size: 11.5px; color: var(--text-muted); margin-top: 4px; }
  #drop-veil {
    position: absolute; inset: 0; z-index: 70;
    display: flex; align-items: center; justify-content: center;
    background: rgba(15,31,58,.10);
    border: 3px dashed var(--btn-fg); border-radius: 8px;
    pointer-events: none;
  }
  #drop-veil .dv-inner {
    display: flex; flex-direction: column; align-items: center; gap: 10px;
    background: var(--panel); padding: 26px 38px; border-radius: 14px;
    box-shadow: 0 12px 40px rgba(15,31,58,.22);
  }
  #drop-veil .dv-icon { font-size: 40px; line-height: 1; }
  #drop-veil .dv-text { font-size: 15px; font-weight: 700; color: var(--text); }
  /* Tiedostorivit */
  /* 2026-06-08: järjestelmä-otsikko piirustusvalitsimessa (ryhmittely järjestelmittäin) */
  .file-sys-head {
    display: flex; align-items: center; gap: 7px;
    padding: 7px 8px 4px; margin-top: 4px;
    font-size: 11px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase;
    color: var(--text-muted); cursor: pointer; border-top: 1px solid var(--border);
    position: sticky; top: 0; background: var(--panel); z-index: 1;
  }
  .file-sys-head:first-child { border-top: none; margin-top: 0; }
  .file-sys-head:hover { color: var(--text); }
  .file-sys-head.active { color: var(--text); }
  .file-sys-head .fsh-ico { font-size: 13px; }
  .file-sys-head .fsh-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .file-sys-head .fsh-badge {
    font-size: 8.5px; font-weight: 700; color: var(--blue); background: #eef4ff;
    border-radius: 99px; padding: 1px 6px; text-transform: none; letter-spacing: 0;
  }
  .file-sys-head.active .fsh-name { color: var(--blue); }
  .file-sys-empty { font-size: 11px; color: var(--text-muted); font-style: italic; padding: 2px 10px 6px 26px; }
  .file-item {
    display: flex; align-items: center;
    gap: 7px; padding: 6px 8px; border-radius: var(--radius-sm);
    cursor: pointer; line-height: 1.3;
  }
  .file-item:nth-child(even) { background: rgba(0,0,0,0.028); }
  .file-item:hover { background: var(--bark-light) !important; }
  /* Aktiivinen tiedosto/sivu: selvä korostus — vasen reuna oranssi paksuna,
     tausta korostettu, fontti vahvempi. Käyttäjä näkee heti mikä on auki. */
  .file-item.active {
    background: rgba(15, 158, 213, 0.12) !important;
    box-shadow: inset 0 0 0 1px rgba(30, 47, 74, 0.30) !important;
    box-shadow: inset 0 0 0 1px rgba(15, 158, 213, 0.25) !important;
  }
  .file-item[data-status="done"] { background: #E6F4E0 !important; }
  .file-item[data-status="done"]:hover { background: #D3ECCb !important; }
  .file-item[data-status="done"].active {
    background: #C6E6BE !important;
    box-shadow: inset 0 0 0 1px rgba(22, 163, 74, 0.55) !important;
  }
  .file-item[data-status="reviewing"] { background: #FFF8E6 !important; }
  .file-item[data-status="reviewing"].active {
    background: #FFF0CC !important;
    box-shadow: inset 0 0 0 1px rgba(234, 179, 8, 0.6) !important;
  }
  .file-name {
    flex: 1; min-width: 0;
  }
  .file-name-stem {
    font-size: 12px; font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--text);
  }
  .file-item.active .file-name-stem { font-weight: 700; }
  .file-name-num {
    font-size: 10px; color: var(--text-muted); font-family: monospace;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Yhteinen ✕-sulkupainike — sama koko & väri kaikkialla.
     28×28 = touch-yhteensopiva (>24×24), Apple-tyylinen pyöristys. */
  .x-btn, .file-del, .prod-del, .np-btn-x {
    background: transparent; border: 0; cursor: pointer;
    font-size: 17px; color: var(--text-muted);
    width: 28px; height: 28px; line-height: 1;
    border-radius: var(--radius-lg); flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background 0.12s, color 0.12s;
    font-family: inherit;
  }
  .x-btn:hover, .file-del:hover, .prod-del:hover, .np-btn-x:hover {
    background: rgba(0,0,0,0.06); color: #c00;
  }
  /* file-del oletuksena hieman näkyvissä (löydettävyys) — täysi opacity hover:lla */
  .file-del { opacity: 0.35; transition: opacity 0.12s, background 0.12s, color 0.12s; }
  .file-item:hover .file-del { opacity: 1; }
  /* PNG-esikatselun lataustila per PDF — pieni piste rivin oikealla puolella */
  .file-png-dot {
    width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
    background: #d4d4d8; margin: 0 4px;
    transition: background 0.2s, box-shadow 0.2s;
  }
  .file-png-dot[data-s="ready"]   { background: #16A34A; box-shadow: 0 0 0 1px rgba(22,163,74,0.25); }
  .file-png-dot[data-s="loading"] { background: #EAB308; animation: file-png-pulse 1.1s ease-in-out infinite; }
  .file-png-dot[data-s="pending"] { background: #d4d4d8; }
  @keyframes file-png-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
  /* 2026-05-24: PDF-lähde-tag mittaviivoissa/hyllyissä — pieni rivin perään tuleva
     klikattava tagi joka avaa kyseisen PDF:n. */
  .meas-src-tag {
    display: inline-block; padding: 0 5px; margin-left: 4px;
    background: #f1f5f9; color: var(--text-muted);
    border: 1px solid var(--border); border-radius: 3px;
    font-size: 10px; font-family: 'JetBrains Mono', ui-monospace, monospace;
    cursor: pointer; vertical-align: middle;
    transition: background 0.1s, color 0.1s;
  }
  .meas-src-tag:hover { background: #e2e8f0; color: var(--text); }
  .meas-src-tag.meas-src-active {
    background: rgba(15,158,213,0.10); color: var(--blue);
    border-color: rgba(15,158,213,0.30);
  }
  /* 2026-05-23 / 2026-05-24: Aktiivisen PDF:n laskenta-alueet (Z) tiedostorivin alla.
     Päivitys 2026-05-24b: vain Z-tila (laskenta-alueet) — A/P siirtyivät oikealle.
     Korostettu vihreä-sävyinen tausta jotta käyttäjä erottaa selvästi "laskentaan
     vaikuttava" lista. */
  .file-zones {
    padding: 6px 8px 6px 22px;
    display: flex; flex-direction: column; gap: 4px;
    background: rgba(22,163,74,0.06);
    border: 1px solid rgba(22,163,74,0.35);
    margin-left: 8px;
    border-radius: 0 6px 6px 0;
  }
  .file-zones:empty { display: none; }
  .file-zones-head {
    font-size: 11px; font-weight: 700; color: #15803D;
    letter-spacing: 0.03em;
    padding: 2px 0 3px;
  }
  .file-zone-row {
    display: flex; align-items: center; gap: 6px;
    padding: 4px 6px; border-radius: 5px;
    font-size: 12px; color: var(--text); background: var(--panel);
    border: 1px solid var(--border);
    transition: background 0.1s;
  }
  .file-zone-row:hover { background: #fafafa; }
  .fz-dot {
    width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0;
    cursor: pointer; border: 1.5px solid rgba(0,0,0,0.12);
    transition: transform 0.1s;
  }
  .fz-dot:hover { transform: scale(1.15); border-color: rgba(0,0,0,0.3); }
  .fz-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .fz-btn {
    background: transparent; border: 0; cursor: pointer;
    padding: 2px 5px; font-size: 12px; line-height: 1; border-radius: var(--radius-sm);
    color: var(--text-muted); opacity: 0.7;
    transition: opacity 0.1s, background 0.1s, color 0.1s;
  }
  .file-zone-row:hover .fz-btn { opacity: 1; }
  .fz-btn:hover { background: rgba(0,0,0,0.08); color: var(--text); }
  .fz-btn.fz-sub:hover { background: rgba(15,31,58,0.14); color: var(--blue); }
  .fz-btn.fz-del:hover { background: rgba(220,38,38,0.12); color: #DC2626; }
  .fz-hole-mark { display: inline-block; margin-left: 4px; padding: 0 4px; font-size: 11px; font-weight: 700; color: var(--blue); background: rgba(15,31,58,0.10); border-radius: 3px; line-height: 1.5; }
  .file-zone-hole-row {
    display: flex; align-items: center; gap: 6px;
    padding: 2px 6px 2px 22px;
    font-size: 11px; color: var(--text-muted);
    border-radius: var(--radius-sm);
    transition: background 0.1s;
  }
  .file-zone-hole-row:hover { background: rgba(15,31,58,0.06); color: var(--text); }
  .file-zone-hole-row .fzh-mark { color: var(--blue); font-weight: 700; }
  .file-zone-hole-row .fzh-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Yhdenmukainen disabled-tila kaikille napeille — ennen mikään ei muuttunut */
  button:disabled, button[disabled] {
    opacity: 0.45 !important;
    cursor: not-allowed !important;
    pointer-events: none;
  }
  .traffic-light {
    width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0;
    border: 1px solid rgba(0,0,0,0.18);
    cursor: pointer; transition: transform 0.12s;
  }
  .traffic-light:hover { transform: scale(1.4); }
  .tl-none      { background: #ccc; }
  .tl-reviewing { background: #f59e0b; }
  .tl-done      { background: #22c55e; }

  /* ── Tiedostopaneelin alatunniste ───────────────────────────────────────── */
  #file-panel-footer {
    padding: 6px 8px;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
  }
  #batch-search-btn {
    width: 100%;
    padding: 5px 8px;
    border: 1px solid var(--border);
    background: var(--panel);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: 12px;
    color: var(--text-muted);
    text-align: center;
  }
  #batch-search-btn:hover { background: var(--bark-light); color: var(--text); }
  #batch-search-btn:disabled { opacity: 0.5; cursor: not-allowed; }

  /* Layer-toiminto AKTIIVINEN 2026-05-05: käyttäjäpyyntö palauttaa Tasot-näkymän.
     Aiempi piilotus poistettu — PyMuPDF tukee OCG-renderöintiä nyt useimmilla PDF-tyypeillä,
     ja työkalu näkyy himmennettynä jos PDF:llä ei ole tasoja. */
  /* ── Layer-popover ──────────────────────────────────────────────────────── */
  #layer-btn {
    position: relative;
  }
  /* 2026-05-05: korostus kun PDF:llä on tasoja → käyttäjä huomaa että voi piilottaa */
  #layer-toggle-btn.has-layers {
    border-color: var(--blue);
    color: var(--blue);
    font-weight: 700;
  }
  #layer-toggle-btn.has-layers:hover {
    background: rgba(233, 113, 50, 0.08);
  }
  #layer-popover {
    display: flex; flex-direction: column;
    position: fixed; top: 98px; right: 0; bottom: 8px; left: auto;
    z-index: 240;
    width: 264px; max-width: calc(100vw - 16px);
    background: var(--panel, #fff);
    border: 1px solid #DDE3EC; border-right: 0;
    border-radius: 10px 0 0 10px;
    box-shadow: -8px 0 24px rgba(15,31,58,.16);
    padding: 0;
    transform: translateX(calc(100% + 4px));
    transition: transform .18s ease;
  }
  /* 2026-05-26 Vaihe 5: layer-toggle-himmennys POISTETTU (käyttäjäpyyntö).
     Vaiheessa 5 vektorit suodattuvat lennossa frontendissä → reaktio on välitön,
     ei tarvita visuaalista "ladataan"-palautetta. Kuva pysyy valkoisena/täyteyteenä
     aina. .layer-toggling-luokka säilyy koodissa mutta sillä ei ole CSS-tehostetta. */
  #page-img.layer-toggling { /* opacity-dip poistettu — kuva ei himmene */ }
  /* 2026-08-03 (mitattu): tasoklikkauksen JÄLKEEN kuva pysyy identtisenä 0,8–2,1 s
     (palvelimen pdfium-render + WebP-enkoodaus = 93–97 % latenssista, eikä siinä ole
     mitattavaa varaa). Aiemmin klikki myös PYYHKI hover-korostuksen heti, joten
     ainoa vihje katosi juuri silloin kun palautetta olisi tarvittu — käyttäjälle jäi
     "menikö klikki perille" -aukko. Nyt korostus JÄÄ näkyviin haaleana kunnes uusi
     rasteri sitoutuu. Maksaa 0 ms ja 0 palvelinkutsua: polku on jo DOMissa.
     ⚠ Tämä ei lyhennä latenssia — se poistaa epätietoisuuden.
     ⚠ `animation: none` on PAKOLLINEN: `#layer-flash-layer path` ajaa layerFlashPulse-
     animaatiota, ja CSS-animaatio VOITTAA tavallisen opacity-määrittelyn kaskadissa
     (mitattu: ilman tätä computed opacity jäi 0.9:ään). Samalla tilat erottuvat:
     sykkivä = "osoitat tätä tasoa", tasainen haalea = "tämä sammutettiin, kuva tulee". */
  #layer-flash-layer.layer-flash-pending path {
    animation: none;
    opacity: .38;
    transition: opacity .12s ease;
  }
  /* 2026-05-25: sortausrivi popoverissa */
  .layer-sort-row {
    display: flex; align-items: center; gap: 4px;
    padding: 5px 8px;
    border-bottom: 1px solid var(--border);
    flex-wrap: wrap;
  }
  .layer-sort-label {
    font-size: 10px; font-weight: 700; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.4px;
    margin-right: 4px;
  }
  .layer-sort-btn {
    font-size: 10px; padding: 2px 6px;
    border: 1px solid var(--border); border-radius: 3px;
    background: var(--panel); cursor: pointer; color: var(--text-muted);
    font-family: inherit;
  }
  .layer-sort-btn:hover { background: var(--bark-light); color: var(--text); }
  .layer-sort-btn.active {
    background: var(--btn-bg); color: var(--btn-fg);
    border-color: var(--btn-fg); font-weight: 600;
  }
  #layer-popover.open { transform: translateX(0); }
  .layer-popover-head {
    display: flex; align-items: center; gap: 8px;
    padding: 9px 12px; background: #0F1F3A; color: #fff;
    border-bottom: 0; margin-bottom: 0; flex: none;
  }
  .layer-popover-head span { font-size: 11px; font-weight: 500; color: #fff; text-transform: uppercase; letter-spacing: 0.06em; flex: 1 1 auto; }
  .layer-popover-head .layer-count-meta { font-family: ui-monospace, monospace; font-size: 11px; color: #8FA3C0; flex: none; text-transform: none; letter-spacing: 0; }
  .layer-popover-head button { font-size: 10px; padding: 2px 7px; border: 1px solid rgba(255,255,255,0.25); border-radius: 4px; background: transparent; cursor: pointer; color: #C7D2E0; font-family: inherit; }
  .layer-popover-head button:hover { background: rgba(255,255,255,0.12); color: #fff; }
  #layer-list { flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; padding: 4px 0; }
  .layer-row {
    display: flex; align-items: center; gap: 9px;
    padding: 5px 12px; cursor: pointer; user-select: none;
    border-bottom: 1px solid #F4F6F9;
  }
  .layer-row:hover { background: var(--bg, #FAFAF7); }
  .layer-row.sel {
    background: #DBE5F0;
    box-shadow: inset 3px 0 0 var(--blue, #1565c0);
    outline: none;
  }
  .layer-row.sel .layer-row-name { color: #1E2F4A; font-weight: 600; }
  .layer-row input[type="checkbox"] { cursor: pointer; accent-color: var(--vec-sel, #1565c0); flex-shrink: 0; }
  .layer-row-name { font-size: 12px; cursor: pointer; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text, #0F1F3A); }
  .layer-row.off .layer-row-name { color: var(--text-muted, #94A3B8); text-decoration: line-through; }
  /* 2026-07-02: tason hover-vilkutus kuvassa + CAD-sammutustyökalu */
  .layer-pick-row { padding: 6px 10px 2px; }
  /* 2026-07-02 käyttäjäpalaute "tee siitä näkyvämpi": pääpainikkeen tyyli (iOS Tinted) */
  #layer-pick-btn {
    width: 100%; font-size: 12px; font-weight: 600; padding: 8px 10px; border-radius: 8px;
    border: 1px solid var(--btn-bg-hover, #C2D2E5); background: var(--btn-bg, #DBE5F0);
    color: var(--btn-fg, #1E2F4A); cursor: pointer; font-family: inherit; text-align: center;
    display: flex; align-items: center; justify-content: center; gap: 6px;
  }
  #layer-pick-btn:hover { background: var(--btn-bg-hover, #C2D2E5); }
  #layer-pick-btn.active { background: var(--canvas-accent, #1565C0); border-color: var(--canvas-accent, #1565C0); color: #fff; }
  body.theme-dark #layer-pick-btn.active { background: #1565C0; border-color: #1565C0; color: #fff; }
  #layer-flash-layer path { animation: layerFlashPulse .8s ease-in-out infinite; }
  @keyframes layerFlashPulse { 0%, 100% { opacity: 0.9; } 50% { opacity: 0.2; } }
  body.layer-pick-on #viewport-wrap, body.layer-pick-on #viewport-wrap * { cursor: crosshair !important; }
  #layer-pick-status {
    position: fixed; left: 50%; bottom: 58px; transform: translateX(-50%); z-index: 805;
    display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 14px;
    max-width: calc(100vw - 32px); border-radius: 999px;
    background: var(--text, #0F1F3A); color: var(--panel, #fff);
    box-shadow: 0 6px 20px rgba(0,0,0,.25); user-select: none;
  }
  #layer-pick-status[hidden] { display: none; }
  #layer-pick-status .lps-dot {
    width: 10px; height: 10px; flex: 0 0 auto; border-radius: 50%;
    background: #60A5FA; box-shadow: 0 0 0 3px rgba(96,165,250,.22);
    animation: mmb-pulse 1.4s ease-in-out infinite;
  }
  #layer-pick-status .lps-text { font-size: 13px; font-weight: 800; white-space: nowrap; }
  #layer-pick-status .lps-hint { color: inherit; opacity: .62; font-size: 11px; white-space: nowrap; }
  #layer-pick-stop {
    border: 0; border-radius: 999px; padding: 5px 12px;
    font-family: inherit; font-size: 12px; font-weight: 600;
    background: var(--panel, #fff); color: var(--text, #0F1F3A); cursor: pointer;
  }
  #layer-pick-stop:hover { background: var(--btn-sec-bg, #F1F5F9); }
  @media (max-width: 760px) { #layer-pick-status .lps-hint { display: none; } }
  /* Footer-ohje popoverissa: pikanäppäinten muistutus */
  .layer-popover-footer {
    padding: 6px 10px; border-top: 1px solid var(--border);
    font-size: 10px; color: var(--text-muted); background: var(--bark-light);
    line-height: 1.6;
  }
  .layer-popover-footer kbd {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px; background: var(--panel); border: 1px solid var(--border);
    padding: 1px 4px; border-radius: 3px; color: var(--text);
    margin: 0 1px;
  }
  /* Layer-list saa focus-renkaan kun se on aktiivinen — Space toimii silloin */
  #layer-list:focus { outline: 2px solid var(--blue, #2563EB); outline-offset: -2px; }
  /* Layer selection bar — näkyy kun käyttäjä on valinnut tasoja */
  #layer-selection-bar {
    padding: 6px 10px; background: #DBE5F0;
    border-bottom: 1px solid var(--blue, #2563EB);
    display: flex; align-items: center; gap: 6px;
    font-size: 11px;
  }
  #layer-selection-count {
    color: #1E2F4A; font-weight: 700; flex: 1;
  }
  #layer-selection-bar button {
    background: var(--panel); border: 1px solid var(--blue, #2563EB);
    color: #1E2F4A; padding: 3px 8px; border-radius: var(--radius-sm);
    font-size: 10px; font-weight: 600; cursor: pointer;
    font-family: inherit;
  }
  #layer-selection-bar button:hover {
    background: #1E2F4A; color: #fff;
  }
  #layer-sel-hide-btn { background: #fee !important; border-color: #c00 !important; color: #c00 !important; }
  #layer-sel-hide-btn:hover { background: #c00 !important; color: #fff !important; }
  #layer-empty { padding: 10px 12px; font-size: 12px; color: var(--text-muted); }
  .layer-search-wrap { padding: 5px 8px; border-bottom: 1px solid var(--border); }
  #layer-search {
    width: 100%; box-sizing: border-box;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: 4px 8px; font-size: 12px; font-family: inherit;
    color: var(--text); background: var(--panel); outline: none;
  }
  #layer-search:focus { border-color: var(--blue); }
  .layer-scope-row {
    padding: 5px 10px; border-top: 1px solid var(--border);
    margin-top: 2px;
  }
  .layer-scope-row label {
    font-size: 11px; color: var(--text-muted);
    cursor: pointer; display: flex; align-items: center; gap: 6px;
  }
  .layer-scope-row input[type="checkbox"] { cursor: pointer; accent-color: var(--blue); }

  /* Mittakaavaindikaattori headerissa — 2026-05-24k CAD-tyyli (kompakti, vaalea) */
  #scale-indicator {
    background: var(--panel); border: 1px solid var(--border);
    height: 26px; padding: 0 8px;
    border-radius: 5px;
    font-size: 11px; font-weight: 700; letter-spacing: 0;
    color: var(--text); cursor: pointer;
    font-family: inherit;
    white-space: nowrap;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
    display: inline-flex; align-items: center; justify-content: center;
    gap: 4px;
  }
  #scale-indicator::before {
    content: 'Mittakaava';
    font-size: 9px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-muted);
  }
  #scale-indicator:hover { background: #fffaf2; border-color: var(--blue); color: var(--blue); }
  #scale-indicator:hover::before { color: var(--blue); }
  #scale-indicator.detected { color: var(--blue); border-color: var(--blue); }
  /* 2026-05-11: PAKOTA TARKISTAMAAN — jos mittakaava ei ole asetettu, varoitus.
     Punainen reuna + sykkivä animaatio jotta käyttäjä huomaa heti. */
  #scale-indicator.unset {
    color: #dc2626; border-color: #dc2626; background: #fef2f2;
    animation: scale-pulse 1.6s ease-in-out infinite;
  }
  #scale-indicator.unset::before { color: #dc2626; }
  @keyframes scale-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(220,38,38,0.4); }
    50% { box-shadow: 0 0 0 4px rgba(220,38,38,0); }
  }

  /* ── Keski-kolumni (toolbar + viewport) ─────────────────────────────────── */
  #center-col {
    display: flex;
    flex-direction: column;
    flex: 1;
    overflow: hidden;
    min-width: 0;
    position: relative; /* 2026-06-05 bake: #canvas-topbar (position:absolute) ankkuroituu tähän (oli runtime-inline) */
  }
  /* 2026-06-04 Tier 3: yhdistetty vasen sivupaneeli — Tiedostot (yläosa, kokoontaitettava)
     + Tuotteet/Tulokset (alaosa). #file-panel ja <aside> siirretään JS:llä tämän sisään. */
  #left-sidebar {
    display: flex; flex-direction: column;
    width: 320px; flex-shrink: 0;
    order: -1; /* 2026-06-05 bake: sivupaneeli ENSIN (vasemmalle); aside on DOM:ssa mainin lopussa */
    position: relative;
    background: var(--panel);
    border-right: 1px solid var(--border);
    overflow: visible; /* 2026-06-05: salli valikkojen/popoverien ulottua paneelin reunan yli (esim. Tasot-popover) ilman leikkausta */
  }
  #left-sidebar > #file-panel {
    width: auto !important; min-width: 0 !important; max-width: none !important;
    border-right: none !important;
    flex: 0 0 auto;
    max-height: 42%;
  }
  /* Tiedostot-osio kokoontaitettavissa otsikkoa klikkaamalla → enemmän tilaa Tuotteille */
  #left-sidebar > #file-panel.files-collapsed { max-height: 40px !important; }
  #left-sidebar > #file-panel.files-collapsed > *:not(.panel-header) { display: none !important; }
  #left-sidebar > #file-panel .panel-header h2 { cursor: pointer; user-select: none; display: flex; align-items: center; gap: 5px; }
  #left-sidebar > #file-panel .panel-header h2::before { content: '▾'; font-size: 10px; color: var(--text-muted); transition: transform 0.15s; }
  #left-sidebar > #file-panel.files-collapsed .panel-header h2::before { content: '▸'; }
  #left-sidebar > aside {
    width: auto !important;
    border-left: none !important;
    flex: 1 1 auto; min-height: 0;
  }
  #left-sidebar #file-panel-handle, #left-sidebar #aside-resize { display: none !important; }
  /* Yhteinen leveyssäätökahva sivupaneelin oikealla reunalla */
  #left-sidebar-handle {
    position: absolute; right: 0; top: 0; bottom: 0;
    width: 6px; cursor: col-resize; z-index: 30;
    background: transparent; transition: background 0.15s;
  }
  #left-sidebar-handle:hover { background: var(--blue); opacity: 0.4; }
  /* 2026-06-05 Countfire: piirustusvalitsin PROMINENTISTI vasemman paneelin ylimpänä (#lt-file-bar) */
  #lt-file-bar { display: flex; align-items: center; gap: 6px; padding: 8px 8px 6px; border-bottom: 1px solid var(--border); background: var(--panel); flex-shrink: 0; }
  #file-chooser-btn {
    display: flex; align-items: center; gap: 8px;
    flex: 1 1 auto; min-width: 0; max-width: none; height: 38px; padding: 0 12px; cursor: pointer;
    background: #f7f9fc; border: 1px solid var(--border); border-radius: 9px;
    font-size: 12.5px; font-weight: 700; color: var(--text); font-family: inherit;
    margin: 0;
  }
  /* ⚙ (Ominaisuudet) + ⋯ (projektin toiminnot) tiedostopalkin oikeassa reunassa (siirretty ylapalkin oikeasta reunasta) */
  #lt-file-bar #feature-admin-btn { width: 34px; height: 38px; }
  #lt-file-bar #project-menu-btn { height: 38px; width: 34px; padding: 0; }
  #file-chooser-btn:hover { border-color: var(--blue); }
  #file-chooser-btn.active { border-color: var(--blue); background: #eff6ff; }
  #file-chooser-btn #file-chooser-label { flex: 1 1 auto; max-width: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
  #file-chooser-btn .fc-caret { color: var(--text-muted); font-size: 12px; margin-left: auto; }
  #file-chooser-btn .fc-ico { font-size: 15px; line-height: 1; }
  /* #file-panel piirustusvalitsin-dropdownina (irrotettu sivupaneelista) */
  #file-panel.file-chooser-dropdown {
    position: fixed; display: none; z-index: 1250;
    width: 340px; max-width: 92vw; max-height: 74vh;
    border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 16px 48px rgba(15,31,58,0.24);
    background: var(--panel); overflow: hidden;
  }
  #file-panel.file-chooser-dropdown.open { display: flex; flex-direction: column; }
  #file-panel.file-chooser-dropdown #file-panel-handle { display: none !important; }

  /* ── Toast-ilmoitukset ───────────────────────────────────────────────────── */
  /* 2026-05-17 KÄYTTÄJÄPYYNTÖ: toast-ilmoitukset on aina nähtävä KAIKKIEN modaalien
     yli — vektorimuokkaus 1700, library 2000, gallery 1500 jne. jäivät peittämään
     toastit kun z-index oli 500. Nostettu 10000:ään → aina päällä. */
  /* 2026-05-24n: Toast-ilmoitukset uudistettu — vaaleampi tausta, SVG-ikoni,
     yhtenäinen muiden modaalien kanssa, soft shadow */
  #toast-container {
    position: fixed;
    bottom: 64px; right: 20px; /* 2026-06-04: nostettu ohje-FAB:n (bottom:18, 36px) yli, ettei toast peity */
    z-index: 10000;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
    max-width: 380px;
  }
  .toast {
    background: var(--panel);
    color: var(--text);
    padding: 10px 14px 10px 12px;
    border-radius: 9px;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    box-shadow: 0 8px 24px rgba(15,31,58,0.18), 0 2px 6px rgba(15,31,58,0.08);
    animation: toast-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
    transition: opacity 0.3s, transform 0.3s;
    border: 1px solid var(--border);
    display: flex; align-items: flex-start; gap: 9px;
    pointer-events: auto;
    letter-spacing: -0.01em;
  }
  .toast::before {
    content: '';
    width: 18px; height: 18px;
    background-position: center; background-repeat: no-repeat; background-size: 18px;
    flex-shrink: 0; margin-top: 1px;
  }
  /* OK-ikoni — vihreä check */
  .toast::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2316a34a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 11.08V12a10 10 0 1 1-5.93-9.14'/%3E%3Cpolyline points='22 4 12 14.01 9 11.01'/%3E%3C/svg%3E");
  }
  .toast.warn {
    border-color: #fde9c8;
    background: #fffbf5;
  }
  .toast.warn::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f59e0b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'/%3E%3Cline x1='12' y1='9' x2='12' y2='13'/%3E%3Cline x1='12' y1='17' x2='12.01' y2='17'/%3E%3C/svg%3E");
  }
  .toast.err {
    border-color: #fbd5d5;
    background: #fff5f5;
  }
  /* 2026-06-27: dark-teema — varoitus/virhe-toastit eivät saa jäädä vaaleaksi (themed-teksti → näkymätön) */
  body.theme-dark .toast.warn { background: rgba(234,179,8,0.15); border-color: rgba(234,179,8,0.45); }
  body.theme-dark .toast.err { background: rgba(220,38,38,0.16); border-color: rgba(220,38,38,0.5); }
  /* 2026-07-25 D21: neutraali tila ("Tallennetaan…", tuntematon tyyppi).
     ILMAN tätä sääntöä luokka putoaisi oletukseen = vihreä check = valheellinen
     onnistumisilmoitus. */
  .toast.info {
    border-color: #dbe5f0;
    background: var(--panel);
  }
  body.theme-dark .toast.info { background: rgba(148,163,184,0.14); border-color: rgba(148,163,184,0.4); }
  .toast.info::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpolyline points='12 7 12 13'/%3E%3Cpolyline points='12 17 12.01 17'/%3E%3C/svg%3E");
  }
  .toast.err::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23dc2626' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='15' y1='9' x2='9' y2='15'/%3E%3Cline x1='9' y1='9' x2='15' y2='15'/%3E%3C/svg%3E");
  }
  @keyframes toast-in {
    from { transform: translateX(40px) scale(0.95); opacity: 0; }
    to   { transform: translateX(0) scale(1);    opacity: 1; }
  }

  /* ── Tulospalkki (#match-stats) — uusi 2026-05-17 ─────────────────────────
     Tilat:
       .ms-empty   = default (ei vielä hakua)
       .ms-loading = haku käynnissä (kursiivi, harmaa)
       .ms-incr    = yhden tuotteen haku valmis (iso "N kpl löytyi" + vilkutus)
       .ms-summary = kokonaishaun yhteenveto (osumat + tuotteet + värialueet)
       .ms-empty-result = haku valmis, 0 osumaa
       .ms-error   = virhe
       .ms-locked  = sivu lukittu / pakkohaku estetty                          */
  #match-stats { line-height: 1.4; }
  #match-stats .ms-empty {
    color: var(--text-muted); font-size: 12.5px; font-style: italic;
  }
  #match-stats .ms-loading {
    color: var(--text-muted); font-size: 12.5px; font-style: italic;
  }
  #match-stats .ms-error {
    color: #dc2626; font-size: 12.5px; font-weight: 500;
  }
  #match-stats .ms-locked {
    color: #16a34a; font-size: 12.5px; font-weight: 500;
  }
  #match-stats .ms-empty-result {
    color: var(--text-muted); font-size: 12.5px;
  }
  /* Per-tuote tulos (incremental) — iso huomionherättäjä */
  #match-stats .ms-incr {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px; border-radius: var(--radius-lg);
    background: #F0FDF4; border: 1px solid #BBF7D0;
  }
  #match-stats .ms-incr-dot {
    width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0;
    border: 1px solid rgba(0,0,0,0.12);
  }
  #match-stats .ms-incr-text { flex: 1; min-width: 0; }
  #match-stats .ms-incr-name {
    font-size: 12px; font-weight: 600; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  #match-stats .ms-incr-count {
    font-size: 18px; font-weight: 800; color: #166534;
    font-family: 'JetBrains Mono', monospace;
    margin-top: 1px; line-height: 1.1;
  }
  #match-stats .ms-incr-time {
    font-size: 10px; color: var(--text-muted);
    font-family: 'JetBrains Mono', monospace;
  }
  /* Vilkahtaa 2 kertaa kun ilmestyy → käyttäjän huomio saa */
  #match-stats .ms-incr.ms-flash {
    animation: ms-flash 0.55s ease-out 2;
  }
  @keyframes ms-flash {
    0%, 100% { background: #F0FDF4; box-shadow: 0 0 0 0 rgba(34,197,94,0); }
    50%      { background: #DCFCE7; box-shadow: 0 0 0 4px rgba(34,197,94,0.25); }
  }
  /* Kokonaishaun yhteenveto */
  #match-stats .ms-summary-head {
    display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
    font-size: 12.5px; color: var(--text);
  }
  #match-stats .ms-summary-total {
    font-weight: 700; color: var(--text);
  }
  #match-stats .ms-summary-time {
    color: var(--text-muted); font-size: 10.5px;
    font-family: 'JetBrains Mono', monospace; margin-left: auto;
  }
  #match-stats .ms-summary-newpill {
    display: inline-block; background: #DCFCE7; color: #166534;
    font-size: 10.5px; font-weight: 700; padding: 1px 6px; border-radius: var(--radius-sm);
    font-family: 'JetBrains Mono', monospace;
  }
  #match-stats .ms-summary-swatches {
    margin-top: 4px; display: flex; flex-wrap: wrap; gap: 7px 10px;
    font-size: 11px;
  }
  #match-stats .ms-sw {
    display: inline-flex; align-items: center; gap: 4px;
    color: var(--text); font-family: 'JetBrains Mono', monospace;
  }
  #match-stats .ms-sw-dot {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    border: 1px solid rgba(0,0,0,0.1);
  }
  #match-stats .ms-sw-more { color: var(--text-muted); font-size: 10px; }

  /* ── Auto-banneri: ei tunnistettavia viivoja ──────────────────────────── */
  #no-vectors-banner {
    display: none; position: absolute; top: 16px; left: 50%;
    transform: translateX(-50%); z-index: 50;
    background: #FEF3C7; color: #78350F;
    border: 1px solid #FBBF24; border-radius: var(--radius-2xl);
    padding: 12px 18px; font-size: 13px; line-height: 1.45;
    box-shadow: 0 6px 24px rgba(0,0,0,0.15);
    align-items: center; gap: 14px;
    max-width: 640px;
  }
  #no-vectors-banner.show { display: flex; }
  #no-vectors-banner span { flex: 1; }
  #no-vectors-banner button {
    flex-shrink: 0;
    padding: 7px 14px; border: none; border-radius: var(--radius-lg);
    background: #B45309; color: #fff; font-weight: 600;
    font-size: 12.5px; cursor: pointer; font-family: inherit;
    transition: background 0.12s ease;
  }
  #no-vectors-banner button:hover { background: #92400E; }

  /* ── H-työkalu: sädedialogi ─────────────────────────────────────────────── */
  #h-radius-popup {
    display: none; position: fixed; z-index: 90;
    background: var(--panel); border: 2px solid var(--blue);
    border-radius: var(--radius-lg); padding: 12px 16px;
    box-shadow: 0 6px 24px rgba(0,0,0,0.2);
    font-size: 13px;
    bottom: 72px; left: 50%; transform: translateX(-50%);
  }
  #h-radius-popup.show { display: block; }
  #h-radius-popup .hrp-title { font-weight: 700; margin-bottom: 8px; color: var(--blue); }
  #h-radius-popup label { display: flex; align-items: center; gap: 8px; }
  #h-radius-popup input[type=number] { width: 64px; padding: 4px 7px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 13px; font-family: inherit; }
  #h-radius-popup .hrp-btns { display: flex; gap: 6px; margin-top: 8px; }
  #h-radius-popup .hrp-btns button { flex: 1; padding: 5px; border-radius: var(--radius-sm); cursor: pointer; font-family: inherit; font-size: 12px; border: 1px solid var(--border); }
  #h-radius-popup .hrp-ok { background: var(--blue); color: #fff; border-color: var(--blue); }

  /* 2026-06-28: Yhtenäinen piirto-aloitusmodaali (Mittaviiva L/H + Reitti T) — nimi pakollinen ennen piirtoa */
  #draw-start-bg { display: none; position: fixed; inset: 0; z-index: 1400; background: rgba(15,31,58,0.32); align-items: center; justify-content: center; }
  #draw-start-bg.show { display: flex; }
  #draw-start-popup { width: 360px; max-width: calc(100vw - 24px); background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-2xl,14px); box-shadow: 0 18px 50px rgba(15,31,58,0.30); overflow: hidden; font-size: 13px; color: var(--text); }
  #draw-start-popup .dsp-title { font-weight: 800; font-size: 14px; padding: 12px 16px; background: var(--navy); color: #fff; }
  #draw-start-popup .dsp-sec { padding: 14px 16px 4px; }
  #draw-start-popup .dsp-field { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
  #draw-start-popup .dsp-field > span { flex: 0 0 92px; color: var(--text-muted); }
  #draw-start-popup .dsp-field input { flex: 1; min-width: 0; padding: 6px 9px; border: 1px solid var(--border); border-radius: var(--radius-sm,7px); font-size: 13px; font-family: inherit; background: var(--panel); color: var(--text); }
  #draw-start-popup .dsp-field input[type=color] { flex: 0 0 46px; height: 30px; padding: 2px; cursor: pointer; }
  #draw-start-popup .dsp-tray-color { -webkit-appearance: none; appearance: none; width: 22px; height: 22px; flex: none; padding: 0; border: 1px solid var(--border); border-radius: 5px; background: none; cursor: pointer; }
  #draw-start-popup .dsp-tray-color::-webkit-color-swatch-wrapper { padding: 0; }
  #draw-start-popup .dsp-tray-color::-webkit-color-swatch { border: none; border-radius: 4px; }
  #draw-start-popup .dsp-hint { font-size: 11px; min-height: 14px; margin: -4px 0 8px 102px; color: var(--text-muted); }
  #draw-start-popup .dsp-hint-ok { color: #15803D; }
  #draw-start-popup .dsp-hint-warn { color: #B45309; }
  #draw-start-popup .dsp-tray-head { font-size: 11px; color: var(--text-muted); margin-bottom: 8px; line-height: 1.35; }
  #draw-start-popup .dsp-tray-row { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; }
  #draw-start-popup .dsp-tray-dot { width: 11px; height: 11px; border-radius: 3px; flex: none; }
  #draw-start-popup .dsp-tray-row input { padding: 6px 9px; border: 1px solid var(--border); border-radius: var(--radius-sm,7px); font-size: 13px; font-family: inherit; background: var(--panel); color: var(--text); }
  #draw-start-popup .dsp-tray-name { flex: 1; min-width: 0; }
  #draw-start-popup .dsp-tray-koko { flex: 0 0 78px; }
  #draw-start-popup .dsp-tray-del { flex: none; border: 1px solid var(--border); background: var(--panel); border-radius: 6px; cursor: pointer; color: var(--text-muted); padding: 4px 7px; }
  #draw-start-popup .dsp-addrow { width: 100%; margin-top: 2px; border: 1px dashed var(--border); background: var(--panel); border-radius: 7px; cursor: pointer; color: var(--blue); padding: 6px; font-family: inherit; font-size: 12px; }
  #draw-start-popup .dsp-instr { padding: 6px 16px 0; font-size: 11px; color: var(--text-muted); line-height: 1.35; }
  #draw-start-popup .dsp-btns { display: flex; gap: 8px; padding: 12px 16px 14px; }
  #draw-start-popup .dsp-btns button { flex: 1; padding: 8px; border-radius: var(--radius-sm,8px); cursor: pointer; font-family: inherit; font-size: 13px; font-weight: 600; border: 1px solid var(--border); background: var(--btn-sec-bg); color: var(--btn-sec-fg); }
  #draw-start-popup .dsp-ok { background: var(--btn-bg); color: var(--btn-fg); border-color: var(--btn-bg); }
  #draw-start-popup .dsp-ok:disabled { opacity: 0.5; cursor: not-allowed; }

  /* ── Johdotus-dialogi ───────────────────────────────────────────────────── */
  #wiring-popup { position: fixed; top: 110px; left: 50%; transform: translateX(-50%); z-index: 1500;
    width: 440px; max-width: calc(100vw - 24px); background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0,0,0,0.30); font-size: 12.5px; overflow: hidden; }
  #wiring-popup .wp-head { display: flex; align-items: center; justify-content: space-between;
    background: #0F1F3A; color: #fff; padding: 9px 12px; font-weight: 700; font-size: 13px; }
  #wiring-popup .wp-est { font-size: 10px; font-weight: 700; letter-spacing: 0.06em; background: rgba(255,255,255,0.14);
    border: 1px solid rgba(255,255,255,0.25); border-radius: 99px; padding: 2px 8px; }
  #wiring-popup .wp-body { padding: 10px 12px 4px; }
  #wiring-popup .wp-meta { color: var(--text-muted); font-size: 11.5px; margin-bottom: 8px; }
  #wiring-popup .wp-row { margin-bottom: 9px; }
  #wiring-popup .wp-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
  #wiring-popup .wp-modes label { display: grid; grid-template-columns: auto 1fr; align-items: start; gap: 2px 7px; padding: 8px;
    border: 1px solid var(--border); border-radius: 8px; cursor: pointer; }
  #wiring-popup .wp-modes input { grid-row: 1 / 3; margin-top: 2px; }
  #wiring-popup .wp-hint { color: var(--text-muted); font-size: 11px; }
  #wiring-popup .wp-grid { display: flex; gap: 10px; }
  #wiring-popup .wp-grid label { flex: 1; }
  #wiring-popup label { display: block; font-weight: 600; }
  #wiring-popup input[type=number], #wiring-popup input[type=text], #wiring-popup select {
    width: 100%; margin-top: 3px; padding: 5px 7px; border: 1px solid var(--border); border-radius: var(--radius-md);
    font-family: inherit; font-size: 12.5px; box-sizing: border-box; }
  #wiring-popup .wp-home { border-top: 1px dashed var(--border); padding-top: 8px; }
  #wiring-popup .wp-product { display:flex; align-items:center; justify-content:space-between; gap:8px;
    border:1px solid var(--border); border-radius:8px; padding:8px; }
  #wiring-popup .wp-product-copy { min-width:0; }
  #wiring-popup .wp-product-copy strong { display:block; }
  #wiring-popup .wp-product-copy small { color:var(--text-muted); display:block; margin-top:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  #wiring-popup .wp-optional { border-top:1px dashed var(--border); padding-top:8px; margin:6px 0 8px; }
  #wiring-popup .wp-optional summary { cursor:pointer; color:var(--text-muted); font-weight:700; }
  #wiring-popup .wp-optional[open] summary { margin-bottom:8px; }
  #wiring-popup .wp-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 9px 12px;
    border-top: 1px solid var(--border); background: var(--panel-soft); }
  #wiring-popup .wp-btn { padding: 6px 13px; border: 1px solid var(--border); border-radius: var(--radius-md);
    background: var(--panel); color: var(--text); cursor: pointer; font-family: inherit; font-size: 12.5px; font-weight: 600; }
  #wiring-popup .wp-btn:hover { background: var(--panel-soft); }
  #wiring-popup .wp-primary { background: var(--btn-bg); color: var(--btn-fg); border-color: var(--btn-bg); }
  #wiring-popup .wp-primary:hover { background: var(--btn-bg-hover); }
  body.wiring-pick #viewport-wrap, body.wiring-pick #viewport-wrap * { cursor: crosshair !important; }

  /* Ketjun tuotevalitsin */
  #chain-product-picker { position:fixed; inset:0; z-index:1800; display:flex; align-items:center; justify-content:center;
    padding:16px; background:rgba(15,31,58,.46); }
  #chain-product-picker .cpp-panel { width:440px; max-width:100%; max-height:min(620px,calc(100vh - 32px));
    display:flex; flex-direction:column; background:var(--panel); color:var(--text); border:1px solid var(--border);
    border-radius:12px; box-shadow:0 18px 50px rgba(0,0,0,.28); overflow:hidden; }
  #chain-product-picker .cpp-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:14px 16px;
    border-bottom:1px solid var(--border); }
  #chain-product-picker .cpp-sub { color:var(--text-muted); font-size:11.5px; margin-top:3px; }
  #chain-product-picker .cpp-x { border:0; background:transparent; color:var(--text-muted); font-size:22px; cursor:pointer; }
  #chain-product-picker .cpp-tools { display:grid; grid-template-columns:1fr auto auto; gap:6px; padding:10px 12px; border-bottom:1px solid var(--border); }
  #chain-product-picker .cpp-search { min-width:0; padding:7px 9px; border:1px solid var(--border); border-radius:8px; background:var(--panel); color:var(--text); }
  #chain-product-picker button { border:1px solid var(--border); border-radius:8px; padding:6px 9px; background:var(--btn-sec-bg); color:var(--btn-sec-fg); cursor:pointer; }
  #chain-product-picker .cpp-list { min-height:120px; overflow:auto; padding:6px 12px; }
  #chain-product-picker .cpp-row { display:grid; grid-template-columns:auto 1fr auto; align-items:center; gap:8px; padding:7px 4px; cursor:pointer; }
  #chain-product-picker .cpp-row.locked { color:var(--text-muted); cursor:default; }
  #chain-product-picker .cpp-row small { font-size:10px; color:var(--text-muted); }
  #chain-product-picker .cpp-empty { padding:24px 4px; text-align:center; color:var(--text-muted); }
  #chain-product-picker .cpp-foot { display:flex; align-items:center; justify-content:flex-end; gap:7px; padding:10px 12px; border-top:1px solid var(--border); }
  #chain-product-picker .cpp-count { margin-right:auto; color:var(--text-muted); font-size:11.5px; }
  #chain-product-picker .cpp-save { background:var(--btn-bg); color:var(--btn-fg); border-color:var(--btn-bg); font-weight:700; }

  /* ═══ 2026-06-11 TEEMA v2: TUMMA KEHYS, VAALEA LUKUPINTA ════════════════════
     Periaate: yläpalkki + työkalu-rail + piirustuksen ympärys = yhtenäinen navy-
     kehys → valkoinen piirustus nousee pääosaan (Lightroom/Countfire-malli).
     Lukupinnat (tuotelista, modaalisisällöt, popoverit, Hub) PYSYVÄT vaaleina —
     tiheä numeroteksti on tarkempi lukea vaalealta pohjalta. Popover-PANEELIT
     (.hdr-menu-panel ym.) säilyttävät oman vaalean taustansa → ei kosketa. */
  :root {
    --chrome: #0F1F3A;        /* kehyksen pohja = railin navy */
    --chrome-2: #16243E;      /* kelluvat sirut (zoom, ?) */
    --chrome-hover: #1B2C47;  /* hover = sama kuin railissa */
    --chrome-border: #24365A; /* reunat/jakajat kehyksessä */
    --chrome-text: #E7EDF6;   /* pääteksti kehyksessä */
    --chrome-dim: #9FB0CC;    /* toissijainen teksti kehyksessä */
  }
  /* ═══ GRAFIITTI-TEEMA (Claude Design -handoff, 2026-06-27, OLETUS) ════════════════════════════════════
     Token-pohjainen teema: viileän vaalea, hiusviivat, accent VAIN aktiivitiloissa (Apple-henkinen).
     body.theme-graphite = vaalea (oletus — <body>-jälkeinen skripti lisää aina paitsi ?theme=b3).
     body.theme-dark (LISÄLUOKKA graphiten päälle) = tumma — Näkymä ▾ -valikon kytkin togglaa + localStorage.
     Korvaa Pehmeä paperi -teeman. ?theme=b3 → alkuperäinen navy-frame B3 (koskematon fallback).
     KAIKKI element-säännöt viittaavat tokeneihin → tumma vaihtaa VAIN tokenit, säännöt seuraavat.
     EI kosketa tunnistukseen/logiikkaan — vain värit. PERUUTUS: poista nämä lohkot + <body>-skripti → B3. */
  body.theme-graphite {
    /* — pohja (handoff Grafiitti · vaalea) — */
    --bg: #F5F5F7; --panel: #FFFFFF; --panel-soft: #F6F6F8;
    --border: #EDEDEF; --border-soft: #F3F3F4;
    --text: #1D1D1F; --text-soft: #5C5C61; --text-muted: #86868B; --text-faint: #9A9AA0;
    --logo: #1D1D1F; --navy: #1D1D1F; --bark-warm: #86868B;
    /* accent = Grafiitti ink (aktiivinen työkalu/välilehti/primary) — EI kosketa --vec-sel:iin
       (canvas-vektorivalinta pysyy sinisenä → näkyy mustien CAD-viivojen päällä) */
    --blue: #1D1D1F; --focus: #1D1D1F; --orange: #1D1D1F;
    --canvas-accent: var(--blue);  /* vaalea: ink (sama kuin ennen) */
    --btn-bg: #1D1D1F; --btn-fg: #FFFFFF; --btn-bg-hover: #000000;
    --btn-sec-bg: #F0F0F2; --btn-sec-fg: #5C5C61;
    /* chrome = vaalea (header/rail/viewbar valkoinen + hiusviiva) */
    --chrome: #FFFFFF; --chrome-2: #FFFFFF; --chrome-hover: #EFEFF1;
    --chrome-border: #EDEDEF; --chrome-text: #1D1D1F; --chrome-dim: #5C5C61;
    /* apuri-tokenit (tumma vaihtaa nämä → element-säännöt seuraavat) */
    --gf-canvas: #EBEBEE; --gf-rail: #FAFAFB; --gf-field: #F6F6F8;
    --gf-accent-soft: #F0F0F2; --gf-on-accent: #FFFFFF;
    --gf-head: #1D1D1F; --gf-head-fg: #FFFFFF; --gf-hairline: #EDEDEF;
    --gf-shadow: 0 6px 20px rgba(0,0,0,.08);
  }
  body.theme-dark {
    /* — pohja (handoff Grafiitti · tumma) — yliajaa graphiten tokenit; element-säännöt seuraavat — */
    --bg: #0F0F12; --panel: #18181C; --panel-soft: #212126;
    --border: #26262B; --border-soft: #2A2A30;
    --text: #F2F2F5; --text-soft: #A6A6AD; --text-muted: #84848C; --text-faint: #7C7C84;
    --logo: #F2F2F5; --navy: #18181C; --bark-warm: #84848C;
    --blue: #F2F2F5; --focus: #F2F2F5; --orange: #F2F2F5;
    --canvas-accent: #1565C0;  /* tumma: sininen — näkyy vaalean PDF:n päällä (--blue olisi lähes valkoinen) */
    --btn-bg: #F2F2F5; --btn-fg: #17171A; --btn-bg-hover: #FFFFFF;
    --btn-sec-bg: #26262B; --btn-sec-fg: #A6A6AD;
    --success-feedback-bg: #14532d; --success-feedback-fg: #dcfce7;
    --warn-feedback-bg: #713f12;    --warn-feedback-fg: #fef3c7;
    --danger-feedback-bg: #7f1d1d;  --danger-feedback-fg: #fee2e2;
    --chrome: #18181C; --chrome-2: #18181C; --chrome-hover: #26262B;
    --chrome-border: #26262B; --chrome-text: #F2F2F5; --chrome-dim: #A6A6AD;
    --gf-canvas: #0C0C0F; --gf-rail: #141417; --gf-field: #212126;
    --gf-accent-soft: #26262B; --gf-on-accent: #17171A;
    --gf-head: #26262B; --gf-head-fg: #F2F2F5; --gf-hairline: #26262B;
    --gf-shadow: 0 8px 28px rgba(0,0,0,.5);
  }
  /* ── Element-uudelleenmaalaus (gated theme-graphite → koskee myös tummaa; tokenit vaihtuvat).
        Yliajaa B3:n navy-frame-perussäännöt (rivit ~3920+ jätetty koskematta = ?theme=b3 fallback). ── */
  /* Rail */
  body.theme-graphite #tool-rail { background: var(--gf-rail); border-right-color: var(--chrome-border); }
  body.theme-graphite #tool-rail .lt-tile, body.theme-graphite #tool-rail .lt-tile.lt-helper { color: var(--text-muted); }
  body.theme-graphite #tool-rail .lt-tile:hover { background: var(--chrome-hover); color: var(--text); }
  /* 2026-08-03: `.lt-open` (pudotus auki) kuuluu samaan aktiivi-ilmeeseen kuin `.active`.
     Ilman sitä avattu valikko näytti lepotilalta — ainoa vihje oli caretin kääntyminen. */
  body.theme-graphite #tool-rail .lt-tile.active,
  body.theme-graphite #tool-rail .lt-tile.lt-open,
  body.theme-graphite #tool-rail .lt-tile[aria-pressed="true"] { background: var(--blue); color: var(--gf-on-accent); border-color: var(--blue); }
  body.theme-graphite #tool-rail .lt-tile.active .lt-caret,
  body.theme-graphite #tool-rail .lt-tile.lt-open .lt-caret { color: var(--gf-on-accent); }
  body.theme-graphite #tool-rail .lt-caret { color: var(--text-faint); }
  body.theme-graphite #tool-rail .lt-rail-sep i { background: var(--chrome-border); }
  body.theme-graphite #tool-rail .lt-rail-sep span { color: var(--text-muted); }
  /* 2026-08-03 KÄYTTÄJÄPALAUTE "Laske-valikko on aina musta": TÄMÄ rivi oli syy.
     `:not(.active)` maalasi LEPOTILAAN täytön (--gf-accent-soft) → jokainen railitiili
     näytti pysyvästi painetulta, ja aktiivisuus erottui vain sävyerona. Täyttö oli
     alun perin taksonomiavihje (päätyökalu vs. apuväline), mutta apuvälinetiiliä ei
     enää ole — kaikki kolme ovat .lt-group, joten se ei erottanut mitään.
     SÄÄNTÖ NYT: täytetty = aktiivinen. Lepo on täytötön, hover himmeä. */
  body.theme-graphite #tool-rail .lt-tile.lt-group:not(.active):not(.lt-open) { background: transparent; border-color: var(--chrome-border); }
  body.theme-graphite #tool-rail .lt-tile.lt-group:hover:not(.active):not(.lt-open) { background: var(--chrome-hover); }
  /* Vaaleiden pintojen aktiivitintit → accent-soft (vaalea harmaa / tumma harmaa).
     HUOM: #left-tools .lt-tile EI tähän — se on railin sisällä → saa accent-fill-säännön yllä. */
  body.theme-graphite .lt-subbar .lt-sub.active,
  body.theme-graphite .lt-subbar .lt-sub[aria-pressed="true"],
  body.theme-graphite .hdr-menu-btn.active,
  body.theme-graphite .hdr-icon-btn.active,
  body.theme-graphite .lt-subbar .lt-sub-detect.active,
  body.theme-graphite #product-list-header .prod-rowicon.active {
    background: var(--gf-accent-soft);
  }
  /* Chromen kovakoodatut B3-arvot (valkoinen teksti/varjo) → token (tumma seuraa automaattisesti) */
  body.theme-graphite #vektoria-brand svg text { fill: var(--chrome-text); }
  body.theme-graphite #project-bar { background: var(--gf-accent-soft) !important; border-color: var(--chrome-border) !important; }
  body.theme-graphite #project-bar #project-bar-name { color: var(--chrome-text) !important; }
  body.theme-graphite #project-bar .pb-icon-btn { color: var(--chrome-dim); }
  body.theme-graphite #project-bar .pb-icon-btn:hover { background: var(--chrome-hover); color: var(--text); }
  body.theme-graphite header .hdr-menu-btn { background: var(--gf-accent-soft); border-color: var(--chrome-border); color: var(--chrome-text); }
  body.theme-graphite header .hdr-menu-btn:hover { background: var(--chrome-hover); color: var(--text); }
  body.theme-graphite #canvas-viewbar .vb-btn,
  body.theme-graphite #canvas-viewbar .hdr-menu-btn { background: var(--gf-accent-soft); border-color: var(--chrome-border); color: var(--chrome-text); }
  body.theme-graphite #canvas-viewbar .vb-btn:hover,
  body.theme-graphite #canvas-viewbar .hdr-menu-btn:hover { background: var(--chrome-hover); color: var(--text); }
  body.theme-graphite #viewport-wrap { background: var(--gf-canvas); }
  body.theme-graphite #viewport { box-shadow: var(--gf-shadow); }
  body.theme-graphite #zoom-controls { background: var(--chrome-2); border-color: var(--chrome-border); box-shadow: var(--gf-shadow); }
  body.theme-graphite #zoom-controls button { color: var(--chrome-text); }
  body.theme-graphite #zoom-controls button:hover { background: var(--chrome-hover); color: var(--text); }
  body.theme-graphite #zoom-controls #zoom-pct { color: var(--chrome-dim); }
  body.theme-graphite html #kbd-help-fab, body.theme-graphite #kbd-help-fab { background: var(--chrome-2); color: var(--chrome-dim); border-color: var(--chrome-border); box-shadow: var(--gf-shadow); }
  body.theme-graphite #kbd-help-fab:hover { background: var(--chrome-hover); color: var(--text); }
  /* Mittakaava-chip (siirretty ribboniin): cream-hover → accent-soft (tumma seuraa) */
  body.theme-graphite #scale-indicator:hover { background: var(--gf-accent-soft); border-color: var(--blue); color: var(--text); }
  body.theme-graphite #scale-indicator:hover::before { color: var(--text); }
  /* Modaali-/popover-otsikkopalkit (navy → graphite-head: vaaleassa ink-musta, tummassa nostettu panel) */
  body.theme-graphite #modal-head { background: var(--gf-head); border-bottom-color: var(--gf-hairline); }
  body.theme-graphite .vk-win-head { background: var(--gf-head); }
  body.theme-graphite .layer-popover-head { background: var(--gf-head); }
  body.theme-graphite #wiring-popup .wp-head { background: var(--gf-head); }
  body.theme-graphite #chain-bar .cb-head { background: var(--gf-head); }
  body.theme-graphite #ui-dialog-head { background: var(--gf-head); }
  body.theme-graphite #ui-dialog-bg { background: rgba(0,0,0,0.45); }
  body.theme-graphite .rb-primary-btn { background: var(--blue); color: var(--gf-on-accent); }
  body.theme-graphite .rb-primary-btn:hover { background: var(--btn-bg-hover); }
  body.theme-graphite .modal-action-btn.modal-action-primary { background: var(--blue); border-color: var(--blue); color: var(--gf-on-accent); }
  body.theme-graphite .modal-action-btn.modal-action-primary:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); }
  body.theme-graphite #meas-edit-modal > div:first-child,
  body.theme-graphite #stamp-picker-modal > div:first-child,
  body.theme-graphite #library-modal > div:first-child,
  body.theme-graphite #gallery-modal > div:first-child,
  body.theme-graphite #copy-sys-modal > div:first-child,
  body.theme-graphite #quantities-modal > div:first-child,
  body.theme-graphite #estimate-modal > div:first-child,
  body.theme-graphite #est-settings-bg > div > div:first-child,
  body.theme-graphite #est-remap-picker-bg > div > div:first-child,
  body.theme-graphite #est-add-product-bg > div > div:first-child,
  body.theme-graphite #laskenta-export-modal > div:first-child,
  body.theme-graphite #batch-summary-modal > div:first-child,
  body.theme-graphite #models-modal > div:first-child {
    background: var(--gf-head) !important; border-bottom-color: var(--gf-hairline) !important;
  }
  /* Mittauksen context-barin työkalunimi-badge: navy → graphite-head */
  body.theme-graphite #dt-toolname { background: var(--gf-head); }
  /* Vaaleansiniset aktiivi-/hover-/badge-taustat (#eef3fb/#eef4ff) → accent-soft.
     Reuna/teksti tulee jo var(--blue)=accent — vain BG jäi kovakoodatuksi siniseksi. */
  body.theme-graphite .product-card.active,
  body.theme-graphite .ribbon-btn.active,
  body.theme-graphite .pap-btn.active,
  body.theme-graphite #canvas-viewbar .vb-btn[aria-pressed="true"],
  body.theme-graphite #canvas-viewbar #layer-toggle-btn.has-layers,
  body.theme-graphite .hdr-menu-panel .rb-btn[aria-pressed="true"],
  body.theme-graphite #hide-bg-btn.active,
  body.theme-graphite #hide-menu-panel .rb-btn.active,
  body.theme-graphite #hide-menu-btn.filt-on,
  body.theme-graphite #revdiff-btn.active,
  body.theme-graphite #systems-list .sys-row:hover,
  body.theme-graphite #draw-ctx-menu .ctx-w-btn:hover,
  body.theme-graphite .rev-menu-pop button:hover,
  body.theme-graphite .diff-base-pop .dbp-item:hover,
  body.theme-graphite .fsh-badge,
  body.theme-graphite .file-rev-badge,
  body.theme-graphite .file-rev-badge.arch,
  body.theme-graphite #diff-panel .dp-warn,
  body.theme-graphite #tool-help-panel .thp-tip {
    background: var(--gf-accent-soft);
  }
  /* Tasot-popoverin otsikkonapit (head:n päällä) → head-fg */
  body.theme-graphite .layer-popover-head button { color: var(--gf-head-fg); }
  /* Kovakoodatut vaaleat pinnat (#f7f9fc/#eff6ff) jotka eivät kääntyneet tummassa → token */
  body.theme-graphite #file-chooser-btn { background: var(--panel); }
  body.theme-graphite #file-chooser-btn.active { background: var(--gf-accent-soft); }
  /* ═══ DARK-MODE KONTRASTIKORJAUKSET (2026-06-27) ════════════════════════════════════════════════════
     Kovakoodatut värit jotka eivät kääntyneet tummassa → näkymätön teksti (käyttäjäpalaute "ei näy").
     Löydetty runtime-kontrastiskannerilla (WCAG-luminanssisuhde < 2.0). Gated body.theme-dark → EI vaikuta vaaleaan. */
  /* (0) 2026-06-28 audit-jatko: vasemman työkaluripan ryhmälaattojen teksti/kärki jäivät juuri alle AA:n
     (--text-muted/--text-faint ryhmälaatan #26262B-pohjalla = 4.06/3.64) → --text-soft (≈6.0). Aktiivilaatta
     säilyttää oman tumma-vaalealla-tekstinsä (tarkempi sääntö voittaa). Vain tumma. */
  body.theme-dark #tool-rail .lt-tile,
  body.theme-dark #tool-rail .lt-tile .lt-caret,
  body.theme-dark .htp-sys-meta,
  body.theme-dark .hdr-menu-btn .hm-caret,
  body.theme-dark .fc-caret { color: var(--text-soft); }
  /* (1) Primary/accent-napit: kovakoodattu valkoinen teksti vaalealla accentilla → on-accent (tumma) */
  body.theme-dark #dt-finish,
  body.theme-dark #cb-straighten,
  body.theme-dark #batch-review-btn,
  body.theme-dark #add-file-btn,
  body.theme-dark #file-pick-btn,
  body.theme-dark #h-radius-ok,
  body.theme-dark #scale-modal-ok,
  body.theme-dark #zone-name-ok,
  body.theme-dark #tray-name-ok,
  body.theme-dark #tray-pair-add-ok,
  body.theme-dark #stamp-name-ok,
  body.theme-dark #marker-name-ok,
  body.theme-dark #measure-confirm-ok,
  body.theme-dark #comment-input-ok,
  body.theme-dark #prep-start-btn,
  body.theme-dark #chain-bar .cb-seg.active { color: var(--gf-on-accent) !important; }
  /* (2) Sekundääri-/peruuta-napit: peritty tumma teksti tummalla pohjalla → vaalea */
  body.theme-dark #batch-clear-btn,
  body.theme-dark #run-match-btn,
  body.theme-dark #zone-name-skip,
  body.theme-dark #tray-name-cancel,
  body.theme-dark #tray-pair-add-cancel,
  body.theme-dark #stamp-name-cancel,
  body.theme-dark #marker-name-skip,
  body.theme-dark #measure-confirm-skip,
  body.theme-dark #comment-input-cancel,
  body.theme-dark #library-siivous-select-all,
  body.theme-dark #library-siivous-clear,
  body.theme-dark #library-siivous-select-not-in-rekisteri,
  body.theme-dark #layer-sel-show-btn,
  body.theme-dark #layer-sel-clear-btn,
  body.theme-dark .dt-shape-btn { color: var(--text) !important; }
  body.theme-dark .dt-shape-btn.active { background: var(--gf-accent-soft) !important; color: var(--text) !important; }
  /* (3) Kovakoodattu vaalea tausta + vaalea token-teksti → tumma tausta */
  body.theme-dark #dt-tray-add,
  body.theme-dark #tray-add-line-btn { background: var(--panel-soft) !important; color: var(--text) !important; }
  body.theme-dark #dt-tray-add:hover { background: var(--chrome-hover) !important; }
  body.theme-dark #draw-ctx-menu .ctx-w-btn { background: var(--panel-soft) !important; color: var(--text) !important; }
  /* (4) Tinted note/warn-laatikot (tausta jo accent-soft graphite-overridessa) → kovakoodattu tumma teksti vaaleaksi */
  body.theme-dark #tool-help-panel .thp-tip,
  body.theme-dark #diff-panel .dp-warn,
  body.theme-dark .file-rev-badge.arch { color: var(--text) !important; }
  /* (6) Sekundääri modal-action-napit (Sulje/Vie laskentaan): kovakoodattu tumma teksti → vaalea
        (EI .modal-action-primary — se saa on-accent-tekstin graphite-säännöstä) */
  body.theme-dark .modal-action-btn:not(.modal-action-primary) { color: var(--text) !important; }
  /* (7) Admin-paneeli (Ctrl+Shift+F): kovakoodattu valkoinen tausta → tumma */
  body.theme-dark #vek-admin { background: var(--panel); color: var(--text); }
  body.theme-dark #vek-admin th.user, body.theme-dark #vek-admin td.user { background: var(--panel); }
  body.theme-dark #vek-admin .va-basic { background: var(--panel-soft); }
  /* ═══ (8) DARK-MODE: AVATUT valikot + :hover/.active-tilat + listanäkymät (2026-06-27 täystesti) ══════
     Aiempi skanneri kattoi vain staattisen DOM:in. Tämä kierros avasi valikot/popoverit JA tutki
     hover/active-tilat. Kovakoodatut vaaleat hover-/status-taustat + tummat/amber-tekstit jotka eivät
     kääntyneet tummassa → näkymättömiä. Kaikki gated body.theme-dark → EI vaikuta vaaleaan teemaan. */
  /* 8a — flyout-/työkaluvalikon hover & aktiivitilat (RAPORTOITU: Mittaa-valikon rivi näkymätön hoverilla) */
  body.theme-dark .lt-subbar .lt-sub:hover { background: var(--chrome-hover); color: var(--text); }
  body.theme-dark .lt-subbar .lt-sub-toggle.active,
  body.theme-dark .lt-subbar .lt-sub-toggle[aria-pressed="true"] { background: var(--gf-accent-soft); }
  body.theme-dark #left-tools .lt-tile.active,
  body.theme-dark #left-tools .lt-tile[aria-pressed="true"] { background: var(--gf-accent-soft); }
  body.theme-dark .ribbon-btn.rb-pan.active { background: var(--gf-accent-soft); border-color: var(--blue); color: var(--blue); }
  /* 2026-06-28: AKTIIVISEN työkalu-tiilen / alivalinnan PAKOTETTU luettava tila tummassa.
     Juurisyy: gf-accent-soft (tumma) -tausta + gf-on-accent (tumma) -teksti → näkymätön
     ("Mittaa valittuna = vain musta"). Selkeä sininen valittu-tila + valkoinen teksti/ikoni. */
  body.theme-dark #tool-rail .lt-tile.active,
  body.theme-dark #tool-rail .lt-tile[aria-pressed="true"],
  body.theme-dark #left-tools .lt-tile.active,
  body.theme-dark #left-tools .lt-tile[aria-pressed="true"],
  body.theme-dark .lt-subbar .lt-sub.active,
  body.theme-dark .lt-subbar .lt-sub[aria-pressed="true"] {
    background: var(--canvas-accent, #1565C0) !important;
    border-color: var(--canvas-accent, #1565C0) !important;
    color: #fff !important;
  }
  body.theme-dark #tool-rail .lt-tile.active svg,
  body.theme-dark #tool-rail .lt-tile[aria-pressed="true"] svg,
  body.theme-dark #left-tools .lt-tile.active svg,
  body.theme-dark .lt-subbar .lt-sub.active svg,
  body.theme-dark .lt-subbar .lt-sub[aria-pressed="true"] svg,
  body.theme-dark #tool-rail .lt-tile.active .lt-caret,
  body.theme-dark #left-tools .lt-tile.active .lt-caret { color: #fff !important; stroke: #fff !important; }
  /* 2026-06-28: "Manuaaliset symbolit" -muokkauspaneeli tummassa — input-tekstit olivat
     mustia (UA-oletus) tummalla pohjalla → näkymättömät; otsikko/koordinaatit liian himmeät. */
  body.theme-dark .marker-edit-panel input[type=text],
  body.theme-dark .marker-edit-panel input[type=number] { color: var(--text); }
  body.theme-dark .marker-singles-head { color: #fbbf24; }
  body.theme-dark .marker-edit-panel .marker-single-item span,
  body.theme-dark .marker-edit-panel .marker-single-del { color: var(--text-soft) !important; }
  body.theme-dark .mep-save-btn { background: #15803D !important; border-color: #15803D !important; }
  body.theme-dark #systems-list .sys-row:hover { background: var(--chrome-hover); }
  /* 8b — ketjupalkin järjestyssegmentti aktiivinen: valkoinen teksti vaalealla accentilla → on-accent */
  body.theme-dark #chain-bar .cb-oseg.active { color: var(--gf-on-accent) !important; }
  /* 8c — manuaalisymbolien tila-chipit (ok/empty/new): kovakoodattu vaalea status-tausta → tumma + vaalea teksti */
  body.theme-dark .mls.ok, body.theme-dark .mls.empty, body.theme-dark .mls.new { background: var(--panel-soft); }
  body.theme-dark .mls.ok .mls-text, body.theme-dark .mls.empty .mls-text, body.theme-dark .mls.new .mls-text { color: var(--text); }
  /* 8d — uuden osuman increment-rivi (match-stats): vaalea flash-tausta → tumma, navy nimi → vaalea */
  body.theme-dark #match-stats .ms-incr { background: var(--panel-soft); }
  body.theme-dark #match-stats .ms-incr-name { color: var(--text); }
  /* 8e — tiedostorivien status-taustat (done/reviewing): vaalea → läpikuultava väritintti (teksti jäi vaaleaksi) */
  body.theme-dark .file-item[data-status="done"] { background: rgba(34,197,94,0.16) !important; }
  body.theme-dark .file-item[data-status="done"]:hover { background: rgba(34,197,94,0.26) !important; }
  body.theme-dark .file-item[data-status="reviewing"] { background: rgba(245,158,11,0.16) !important; }
  body.theme-dark .file-item[data-status="reviewing"]:hover { background: rgba(245,158,11,0.26) !important; }
  /* 8f — Uusi projekti -modaali (oma h2/label, ei modal-head-infraa): tumma navy/slate teksti → vaalea */
  body.theme-dark #hub-new-modal h2 { color: var(--text); }
  body.theme-dark #hub-new-modal label { color: var(--text-soft); }
  /* 8g — työkalu-flyout-napin nimi (#line-flyout-btn): peritty musta teksti tummalla → token */
  body.theme-dark #line-flyout-btn,
  body.theme-dark #line-flyout-btn .ft-label,
  body.theme-dark #line-flyout-btn .ft-chevron { color: var(--text); }
  /* 8h — datatekstit jotka jäivät liian tummiksi tummalla pohjalla: tuotekortin osumamäärä (sininen) +
        amber-toiminta-/varoitustekstit joiden TAUSTA on tumma (ei vaalea chip) → vaaleampi sävy */
  body.theme-dark .product-meta.has-matches { color: #7ea8ff; }
  /* 2026-07-21: no-matches puuttui tummasta → vaalea #cbd5e1 (vaalealle taustalle
     tarkoitettu himmennys) näkyi tummalla KIRKKAAMPANA kuin has-matches-sininen,
     eli "ei osumia" korostui enemmän kuin "on osumia". Sävy tummalle. */
  body.theme-dark .product-meta.no-matches { color: var(--text-faint); }
  body.theme-dark #hub-new-designer-hint-apply,
  body.theme-dark #stamp-counter-undo,
  body.theme-dark #stamp-counter-stop { color: #fcd34d !important; }
  /* 8i — <select>-pudotusvalikot tummiksi (option-tekstit olivat vaaleita valkoisella) */
  body.theme-dark select, body.theme-dark select option { background: var(--panel); color: var(--text); }
  /* 8j — vasemman systeemilistan kovakoodattu vaalea tausta (normaalisti piilossa) → tumma */
  body.theme-dark #systems-bar, body.theme-dark #systems-list { background: var(--panel); }
  body.theme-dark #systems-list .sys-row { background: transparent; }
  /* 8k — leima-rotaationapit (0°/90°/180°/270°): peritty musta teksti tummalla pohjalla → token */
  body.theme-dark button[data-stamp-rot] { color: var(--text); }
  /* 8l — kbd-näppäinmerkit: kovakoodattu vaalea badge-tausta → tumma (esim. ⌃Z stamp-counterissa oli näkymätön) */
  body.theme-dark kbd { background: var(--panel-soft) !important; color: var(--text) !important; border-color: var(--border) !important; }
  /* 8m — prep-/aloitusohjeen lista (inline color:#333) → token */
  body.theme-dark #prep-guide ol,
  body.theme-dark #prep-guide li,
  body.theme-dark #prep-guide b { color: var(--text) !important; }
  /* 8n — "Manuaaliset symbolit" -korostusotsikko (amber #92400e liian tumma tummalla) → vaaleampi amber */
  body.theme-dark .ann-section-prominent h3 { color: #fcd34d; }
  header { background: var(--chrome); border-bottom-color: var(--chrome-border); box-shadow: none; }
  #vektoria-brand svg text { fill: #FFFFFF; }
  #hdr-center { border-top-color: var(--chrome-border); }
  header #status { color: var(--chrome-dim); }
  #bg-tasks-indicator { color: var(--chrome-dim) !important; }
  #project-bar { background: rgba(255,255,255,0.07) !important; border-color: var(--chrome-border) !important; }
  #project-bar #project-bar-name { color: var(--chrome-text) !important; }
  #project-bar .pb-icon-btn { color: var(--chrome-dim); }
  #project-bar .pb-icon-btn:hover { background: var(--chrome-hover); color: #fff; }
  header .hdr-menu-btn { background: rgba(255,255,255,0.07); border-color: var(--chrome-border); color: var(--chrome-text); }
  header .hdr-menu-btn:hover { background: var(--chrome-hover); border-color: var(--chrome-border); color: #fff; }
  #canvas-viewbar { background: var(--chrome); border-bottom-color: var(--chrome-border); }
  #canvas-viewbar .vb-btn, #canvas-viewbar .hdr-menu-btn { background: rgba(255,255,255,0.07); border-color: var(--chrome-border); color: var(--chrome-text); }
  #canvas-viewbar .vb-btn:hover, #canvas-viewbar .hdr-menu-btn:hover { background: var(--chrome-hover); color: #fff; }
  #viewport-wrap { background: #262B33; }   /* lämmin teräs — eri sävy kuin kehys → kangas erottuu */
  #viewport { box-shadow: 0 2px 18px rgba(0,0,0,0.45); }  /* paperi pöydällä */
  #zoom-controls { background: var(--chrome-2); border-color: var(--chrome-border); box-shadow: 0 6px 20px rgba(0,0,0,0.35); }
  #zoom-controls button { color: var(--chrome-text); }
  #zoom-controls button:hover { background: var(--chrome-hover); color: #fff; border-color: var(--chrome-border); }
  #zoom-controls #zoom-pct { color: var(--chrome-dim); }
  html #kbd-help-fab { background: var(--chrome-2); color: var(--chrome-dim); border-color: var(--chrome-border); box-shadow: 0 2px 10px rgba(0,0,0,0.35); }
  html #kbd-help-fab:hover { background: var(--chrome-hover); color: #fff; }

  /* ═══════════════════════════════════════════════════════════════════════════
     DARK-TEEMA: KATTAVA KONTRASTIKORJAUS (2026-06-27, auto-generoitu CSS-skannista)
     Juurisyy: ~240 element-saantoa kovakoodasi vaalean taustan (esim. #fff/#fafbfc)
     + teksti var(--text) → tummassa teksti vaalenee mutta tausta jaa vaaleaksi →
     vaalea teksti vaalealla = lukukelvoton (koko Hub, Estimaattori, modaalit, paneelit).
     Korjaus: token-pohjaiset tummat vastineet VAIN body.theme-dark-skooppissa → vaalea
     teema KOSKEMATON (kaikki saannot ovat additiivisia ja voittavat spesifisyydella).
     EI kosketa tunnistukseen/logiikkaan. Skanneri+generaattori: _perf? (scratchpad).
     ═══════════════════════════════════════════════════════════════════════════ */
/* ═══ DARK-TEEMA KATTAVA KONTRASTIKORJAUS (auto-generoitu skannista 2026-06-27) ═══
   241 kovakoodattua vaaleaa pintaa → token-pohjaiset tummat vastineet. VAIN body.theme-dark → vaalea teema KOSKEMATON. */
body.theme-dark .lt-subbar #new-product-btn.lt-sub-primary[data-sckey]::after,
body.theme-dark .edit-overlay-btn,
body.theme-dark .product-card.sig-drop-over,
body.theme-dark .vk-win,
body.theme-dark #ctx-bar,
body.theme-dark .mls .mls-suggest-btn,
body.theme-dark .mls .mls-suggest-btn:hover,
body.theme-dark .mfoot-stat-old-styles,
body.theme-dark #layer-popover,
body.theme-dark #chain-bar,
body.theme-dark #ml-sample-panel,
body.theme-dark #ml-line-modal .mlm-tool,
body.theme-dark #hub-header,
body.theme-dark #vek-admin .va-head,
body.theme-dark #vek-acct-menu,
body.theme-dark #vek-pw { background:var(--panel); color:var(--text); }
body.theme-dark #estimate-modal > div:first-child button:not(.modal-action-primary),
body.theme-dark #estimate-modal > div:first-child button:not(.modal-action-primary):hover { background:var(--panel) !important; color:var(--text) !important; }
body.theme-dark .template-grid,
body.theme-dark #diff-panel .dp-head,
body.theme-dark #diff-panel .dp-affected,
body.theme-dark .batch-queue-item,
body.theme-dark .stats,
body.theme-dark #modal-body,
body.theme-dark #modal-foot,
body.theme-dark .file-zone-row:hover,
body.theme-dark .layer-row:hover,
body.theme-dark #chain-bar .cb-name:focus,
body.theme-dark #chain-bar .cb-seg:hover:not(.active),
body.theme-dark #chain-bar .cb-oseg:hover:not(.active),
body.theme-dark #chain-bar .cb-pill,
body.theme-dark #chain-bar .cb-mrow:hover,
body.theme-dark #ml-line-modal .mlm-tool:hover,
body.theme-dark #ml-sample-panel .mls-result,
body.theme-dark #ml-sample-panel .mls-fp,
body.theme-dark #ml-sample-panel .mls-half-note,
body.theme-dark #ml-sample-panel .mls-rowbtns .mls-btn:hover,
body.theme-dark #ml-sample-panel .mls-foot .mls-btn:hover,
body.theme-dark #ml-sample-panel .mls-seg,
body.theme-dark #ml-sample-panel .mls-wchip,
body.theme-dark #ml-sample-panel .mls-layerpick,
body.theme-dark #stamp-picker-grid .sp-card:hover,
body.theme-dark .kbd-row kbd,
body.theme-dark #hub-overlay,
body.theme-dark .hub-list-header,
body.theme-dark .hub-tree-panel,
body.theme-dark #quantities-table-wrap th.qm-rowhead,
body.theme-dark #quantities-table-wrap td.qm-rowhead,
body.theme-dark #estimate-content .est-subsection-head,
body.theme-dark #estimate-content .est-table th,
body.theme-dark #estimate-content .est-table tbody tr:hover,
body.theme-dark #estimate-content .est-ext-toolbar,
body.theme-dark #estimate-content .est-ext-row.est-ext-rejected,
body.theme-dark #estimate-content .ext-sys-dropzone:hover,
body.theme-dark #estimate-content .est-vaiheet-detail-tr td.est-vaiheet-detail-td,
body.theme-dark #models-grid .ml-product-head,
body.theme-dark #models-grid .ml-thumb-meta { background:var(--panel-soft); color:var(--text); }
body.theme-dark .product-name-input,
body.theme-dark #modal-head input,
body.theme-dark #ml-line-modal .mlm-seg-ctrl label:has(input:checked),
body.theme-dark #ml-sample-panel #mls-layer-pick,
body.theme-dark #hub-search,
body.theme-dark #hub-sort,
body.theme-dark #hub-new-modal input { background:var(--gf-field); color:var(--text); }
body.theme-dark #meas-edit-modal > div:first-child input,
body.theme-dark #stamp-picker-modal > div:first-child input,
body.theme-dark #library-modal > div:first-child input,
body.theme-dark #library-modal > div:first-child select,
body.theme-dark #gallery-modal > div:first-child select,
body.theme-dark #quantities-modal > div:first-child input,
body.theme-dark #models-modal > div:first-child input { background:var(--gf-field) !important; color:var(--text) !important; }
body.theme-dark #project-menu-panel .hdr-icon-btn:hover,
body.theme-dark #project-menu-panel .rb-btn:hover,
body.theme-dark .hdr-menu-btn:hover,
body.theme-dark .hdr-menu-panel .rb-btn:hover,
body.theme-dark .hdr-menu-panel .hdr-icon-btn:hover,
body.theme-dark .rb-field:hover,
body.theme-dark .panel-header button:hover,
body.theme-dark #new-product-row,
body.theme-dark .product-card.new-placeholder,
body.theme-dark .product-card.pending-input,
body.theme-dark .hdr-icon-btn:hover,
body.theme-dark .ribbon-btn:hover,
body.theme-dark .project-btn:hover,
body.theme-dark .pap-btn:hover,
body.theme-dark .add-link-btn,
body.theme-dark #diff-panel .dp-info,
body.theme-dark .batch-queue-item.searched,
body.theme-dark .tray-card.row-hl,
body.theme-dark .product-card.row-hl,
body.theme-dark .match-section-head button:hover,
body.theme-dark .file-sys-head .fsh-badge,
body.theme-dark .layer-row.sel,
body.theme-dark #layer-selection-bar,
body.theme-dark #ml-line-modal button.mlm-primary:hover,
body.theme-dark #ml-sample-panel .mls-primary:hover,
body.theme-dark .ctx-item:hover,
body.theme-dark #stamp-picker-grid .sp-card.selected,
body.theme-dark .hub-list-row .hl-actions button:hover,
body.theme-dark .hub-list-row.new,
body.theme-dark .hub-list-row.new:hover,
body.theme-dark #hub-overlay.drag-over,
body.theme-dark .htp-sys-import:hover,
body.theme-dark .htp-addsys:hover,
body.theme-dark #quantities-table-wrap tbody tr:hover td:not(.qm-rowhead):not(.qm-total),
body.theme-dark #est-settings-bg .set-btn-primary:hover,
body.theme-dark .est-sec-head:hover,
body.theme-dark .est-input.est-overridden,
body.theme-dark #estimate-content .est-ext-attach-chip,
body.theme-dark #estimate-content .ext-sys-dropzone.drop-active,
body.theme-dark #vek-acct-menu #vek-acct-name-save:hover { background:var(--gf-accent-soft); color:var(--text); }
body.theme-dark #feature-admin .fa-preset,
body.theme-dark .rb-btn:hover,
body.theme-dark #new-product-cancel,
body.theme-dark .prod-text-badge.prod-text-filled,
body.theme-dark #diff-panel .dp-row:hover,
body.theme-dark #manual-mode-banner .mmb-stop:hover,
body.theme-dark .admin-row button:hover,
body.theme-dark .meas-src-tag,
body.theme-dark .meas-src-tag:hover,
body.theme-dark #chain-bar .cb-sep,
body.theme-dark #chain-bar .cb-qbtn,
body.theme-dark #chain-bar .cb-mode,
body.theme-dark #chain-bar .cb-act,
body.theme-dark #chain-bar .cb-mval,
body.theme-dark #ml-line-modal button.mlm-measure:hover,
body.theme-dark #ml-line-modal .mlm-seg-ctrl,
body.theme-dark #ml-line-modal button.mlm-manual:hover,
body.theme-dark #ml-sample-panel .mls-btn,
body.theme-dark #ml-sample-panel .mls-acc-add,
body.theme-dark .hub-btn.ghost:hover,
body.theme-dark #hub-new-modal h2::before,
body.theme-dark #hub-new-modal .actions .hub-btn.ghost,
body.theme-dark #hub-new-modal .actions .hub-btn.ghost:hover,
body.theme-dark .hl-expand:hover,
body.theme-dark .htp-syschev:hover:not([disabled]),
body.theme-dark .htp-sys-import,
body.theme-dark .htp-export,
body.theme-dark #est-settings-bg .set-reg-status,
body.theme-dark #est-settings-bg .set-row button,
body.theme-dark #estimate-tabs .est-tab:hover,
body.theme-dark #estimate-content .est-ext-status-label,
body.theme-dark #vek-acct-menu button:hover,
body.theme-dark #vek-pw .cancel { background:var(--btn-sec-bg); color:var(--btn-sec-fg); }
body.theme-dark #meas-edit-modal > div:first-child button,
body.theme-dark #stamp-picker-modal > div:first-child button,
body.theme-dark #library-modal > div:first-child button,
body.theme-dark #gallery-modal > div:first-child button,
body.theme-dark #copy-sys-modal > div:first-child button,
body.theme-dark #quantities-modal > div:first-child button,
body.theme-dark #est-settings-bg > div > div:first-child button,
body.theme-dark #est-remap-picker-bg > div > div:first-child button,
body.theme-dark #est-add-product-bg > div > div:first-child button,
body.theme-dark #laskenta-export-modal > div:first-child button,
body.theme-dark #batch-summary-modal > div:first-child button,
body.theme-dark #models-modal > div:first-child button,
body.theme-dark #meas-edit-modal > div:first-child button:hover,
body.theme-dark #stamp-picker-modal > div:first-child button:hover,
body.theme-dark #library-modal > div:first-child button:hover,
body.theme-dark #gallery-modal > div:first-child button:hover,
body.theme-dark #copy-sys-modal > div:first-child button:hover,
body.theme-dark #quantities-modal > div:first-child button:hover,
body.theme-dark #laskenta-export-modal > div:first-child button:hover,
body.theme-dark #batch-summary-modal > div:first-child button:hover,
body.theme-dark #models-modal > div:first-child button:hover { background:var(--btn-sec-bg) !important; color:var(--btn-sec-fg) !important; }
body.theme-dark #modal-refresh-view.is-active,
body.theme-dark #chain-bar .cb-act.primary,
body.theme-dark #ml-line-modal .mlm-tool.mlm-tool-on,
body.theme-dark #ml-sample-panel .mls-primary,
body.theme-dark #ml-sample-panel .mls-seg-btn.on,
body.theme-dark #ml-sample-panel .mls-acc-add:hover,
body.theme-dark .htp-addsys,
body.theme-dark .htp-export:hover,
body.theme-dark #est-settings-bg .set-btn-primary,
body.theme-dark #est-settings-bg .set-row button.primary,
body.theme-dark #vek-admin .va-close,
body.theme-dark #vek-acct-menu #vek-acct-name-save,
body.theme-dark #vek-pw .save { background:var(--btn-bg); color:var(--btn-fg); }
body.theme-dark .prod-text-badge,
body.theme-dark .pap-btn-warn,
body.theme-dark .pap-btn-warn:hover,
body.theme-dark .redundancy-badge,
body.theme-dark .redundancy-badge:hover,
body.theme-dark .add-link-btn:hover,
body.theme-dark #stamp-counter,
body.theme-dark #stamp-counter button:hover,
body.theme-dark #stamp-counter kbd,
body.theme-dark .ann-section-prominent,
body.theme-dark .marker-edit-panel,
body.theme-dark .mep-actions button:hover,
body.theme-dark #no-vectors-banner,
body.theme-dark #ml-sample-panel .mls-warn,
body.theme-dark .est-chip-warn,
body.theme-dark #estimate-totals .est-strip-optio,
body.theme-dark #estimate-totals .est-strip-warn,
body.theme-dark #estimate-totals .est-strip-warn:hover,
body.theme-dark .est-summary-option-row td,
body.theme-dark #estimate-content .est-optio-row,
body.theme-dark #estimate-content .est-reset-btn:hover,
body.theme-dark #estimate-content .est-input.est-overridden { background:rgba(234,179,8,.14); color:#fbbf24; }
body.theme-dark .file-item[data-status="reviewing"].active { background:rgba(234,179,8,.14) !important; color:#fbbf24 !important; }
body.theme-dark #project-menu-panel .danger:hover,
body.theme-dark .tgrid-del,
body.theme-dark .tgrid-del:hover,
body.theme-dark .batch-queue-item.rejected,
body.theme-dark .dt-tray-row .dt-tray-rdel:hover,
body.theme-dark #meas-ctx-menu .mcm-danger:hover,
body.theme-dark .ann-del-btn:hover,
body.theme-dark .marker-single-del:hover,
body.theme-dark .admin-row button.danger:hover,
body.theme-dark #scale-indicator.unset,
body.theme-dark #ml-sample-panel .mls-btn.mls-active,
body.theme-dark .ctx-item-danger:hover,
body.theme-dark .hub-list-row .hl-actions button.del:hover,
body.theme-dark #est-settings-bg .set-reg-foot button.danger,
body.theme-dark .est-chip-err { background:rgba(220,38,38,.16); color:#fca5a5; }
body.theme-dark #layer-sel-hide-btn { background:rgba(220,38,38,.16) !important; color:#fca5a5 !important; }
body.theme-dark .batch-queue-item.reviewed,
body.theme-dark #match-stats .ms-summary-newpill,
body.theme-dark #est-settings-bg .set-reg-status.on,
body.theme-dark .est-chip-ok,
body.theme-dark #estimate-content .est-ext-row.est-ext-accepted,
body.theme-dark #estimate-content .est-ext-row.est-ext-accepted .est-ext-status-label { background:rgba(34,197,94,.14); color:#86efac; }
body.theme-dark .file-item[data-status="done"].active { background:rgba(34,197,94,.14) !important; color:#86efac !important; }
  /* ── dark-text korjaus: kovakoodattu tumma teksti → luettava vaalea (vain theme-dark) ── */
  body.theme-dark #stamp-counter .sc-name,
  body.theme-dark #stamp-counter button,
  body.theme-dark #stamp-counter button.sc-stop,
  body.theme-dark .mep-row label,
  body.theme-dark .mep-actions button,
  body.theme-dark .mls.empty,
  body.theme-dark #quantities-table-wrap .qm-own,
  body.theme-dark .est-summary-option-row td:first-child { color:#fbbf24; }
  body.theme-dark #estimate-content .est-ext-attach-chip a { color:#93b4ff; }
  body.theme-dark #diff-panel .dp-empty,
  body.theme-dark .mls.ok,
  body.theme-dark #match-stats .ms-locked,
  body.theme-dark #match-stats .ms-incr-count,
  body.theme-dark #est-settings-bg .set-reg-msg.ok,
  body.theme-dark #vek-pw .msg.ok { color:#86efac; }
  body.theme-dark .modal-action-btn,
  body.theme-dark .layer-row.sel .layer-row-name,
  body.theme-dark #layer-selection-count,
  body.theme-dark #layer-selection-bar button,
  body.theme-dark .kbd-row,
  body.theme-dark .htp-pdf-row,
  body.theme-dark #est-settings-bg .set-step-t,
  body.theme-dark #estimate-totals .est-strip-tarjous b,
  body.theme-dark #vek-admin h3,
  body.theme-dark #vek-acct-menu button,
  body.theme-dark #vek-acct-profile .vap-email,
  body.theme-dark #vek-acct-profile .vap-namerow input,
  body.theme-dark #vek-pw h3 { color:var(--text); }
  body.theme-dark #diff-panel .dp-x,
  body.theme-dark #diff-panel .dp-sub,
  body.theme-dark #diff-panel .dp-num,
  body.theme-dark #diff-panel .dp-cnt,
  body.theme-dark #diff-panel .dp-body,
  body.theme-dark .file-rev-toggle,
  body.theme-dark .file-rev-menu,
  body.theme-dark .admin-row button,
  body.theme-dark .ac-item.ac-existing .ac-desc,
  body.theme-dark .mls.new,
  body.theme-dark #hub-header .hub-sub,
  body.theme-dark #est-settings-bg .set-sec-note,
  body.theme-dark #est-settings-bg .set-step-d,
  body.theme-dark #estimate-content .est-attach-del,
  body.theme-dark #vek-admin th,
  body.theme-dark #vek-acct-profile .vap-cap,
  body.theme-dark #vek-acct-profile .vap-meta,
  body.theme-dark #vek-pw label { color:var(--text-soft); }
  body.theme-dark #project-menu-panel .danger,
  body.theme-dark #diff-panel .dp-x:hover,
  body.theme-dark .admin-row button.danger,
  body.theme-dark .x-btn:hover,
  body.theme-dark .file-del:hover,
  body.theme-dark .prod-del:hover,
  body.theme-dark .np-btn-x:hover,
  body.theme-dark .fz-btn.fz-del:hover,
  body.theme-dark #scale-indicator.unset::before,
  body.theme-dark #match-stats .ms-error,
  body.theme-dark .ctx-item-danger,
  body.theme-dark .hnf-row .hnf-del:hover,
  body.theme-dark #est-settings-bg .set-reg-msg.err,
  body.theme-dark #estimate-content .est-del-btn:hover,
  body.theme-dark #estimate-content .est-attach-del:hover,
  body.theme-dark #vek-pw .msg.err { color:#fca5a5; }


/* ═══ MOTION-PERUSTA (2026-07-10, Emil Kowalski -auditti) ═══════════════════ */

/* Painalluspalaute: käyttöliittymä kuittaa painalluksen (scale 0.97, 160ms ease-out).
   Kohdennettu — EI globaali button-selektori (canvas-työkalunapit + modaalien
   erikoisnapit arvioidaan erikseen). transform-transition EI riko olemassa olevia
   background/color-transitioneita: .hdr-menu-btn/.lt-tile/.project-btn saivat
   transform-propertyn YHDISTETTYNÄ omaan transition-listaansa (01-base-1/-3.css) —
   alla vain luokat joilla ei ollut transitionia ennestään.
   KONFLIKTIEN TAKIA POISJÄTETYT (auditti 2026-07-10): .rb-btn + .pap-btn (hover-nosto
   translateY(-1px), pap-btn:llä oma :active-palaute jo), .hub-card (hover-nosto
   translateY(-2px)), .dt-btn (0 käyttöä markupissa, jakaa säännöt .rb-dt:n kanssa
   jolla hover-transform), .est-btn (luokkaa ei ole olemassa). */
.vb-btn, .vk-win-btn, button.primary {
  transition: transform var(--dur-press) var(--ease-out);
}
.vb-btn:active, .vk-win-btn:active, button.primary:active,
.project-btn:active, .hdr-menu-btn:active, .lt-tile:active {
  transform: scale(0.97);
}

/* Saavutettavuus: liikeherkkyys — transform-liikkeet pois, opacity-feidit jäävät
   (auttavat hahmottamista). Emil: reduced motion = vähemmän ja hillitympää, ei nollaa. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* POIKKEUS: spinnerit VÄLITTÄVÄT TILAA (lataus käynnissä) — jäätynyt spinneri
     näyttäisi jumiutuneelta. .hp-spin = hp-rot-spinnerit (hub/prep, 4 varianttia);
     [style*="prep-spin"] = inline-tyylin prep-spin-spinnerit (index.html + app-12.js).
     Luokkaselektori (0,1,0) voittaa *-säännön (0,0,0) myös !important-kilpailussa.
     Pulse-indikaattorit (layer-pulse, file-png-pulse ym.) EIVÄT tarvitse poikkeusta:
     jäätyneenäkin väri/himmennys kertoo tilan. */
  .hp-spin, [style*="prep-spin"] {
    animation-duration: 0.8s !important;
    animation-iteration-count: infinite !important;
  }
}

    /* 2026-05-30 v3: dockattu OIKEAAN reunaan tuotelistan (aside) kohdalle — EI
       enää peitä piirtoaluetta (canvas). v2:n vasen-sijainti (left:14, 440px)
       valui silti canvasin päälle (x:14–454). Käyttäjäpyyntö: "ketjutyökalu ei
       saa olla viewportin edessä ollenkaan". Ketjutilassa tuotelistaa ei tarvita
       → paneeli saa olla sen päällä; katoaa kun ketjutila päättyy. Leveys 284px
       mahtuu oletus-aside (300px) päälle, ei valu center-coliin tyypillisillä
       leveyksillä. Aside-resize säätää asidea inline-tyylillä; jos käyttäjä
       kaventaa asiden alle ~300px, paneeli voi marginaalisesti ylittää reunan. */
    /* 2026-06-11b: max-height + scroll — paneeli EI valu zoom/?-nappien alle (alavara 72px) */
    #chain-bar{position:fixed;right:8px;left:auto;top:98px;z-index:140;display:none;
      background:var(--panel,#fff);border:1px solid var(--border,#E8EDF3);border-radius: var(--radius-2xl);
      box-shadow:0 8px 28px rgba(15,31,58,0.18);padding:8px 11px;width:320px;max-width:calc(100vw - 16px);
      font-size:12.5px;color:var(--text,#0F1F3A);
      max-height:calc(100vh - 175px);overflow-y:auto;overscroll-behavior:contain;}
    #chain-bar.visible{display:block;}
    #chain-bar .cb-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
    #chain-bar .cb-sep{width:1px;align-self:stretch;background:var(--border,#E8EDF3);margin:0 2px;}
    #chain-bar .cb-swatch{width:17px;height:17px;border-radius:5px;border:2px solid #fff;
      box-shadow:0 0 0 1px rgba(0,0,0,0.18);cursor:pointer;flex:none;}
    #chain-bar .cb-name{font-weight:700;border:none;background:transparent;font-size:13px;
      color:var(--text,#0F1F3A);flex:1;min-width:60px;padding:2px 4px;border-radius: var(--radius-md);}
    #chain-bar .cb-name:focus{background:var(--bg,#FAFAF7);outline:1px solid var(--blue,#0F9ED5);}
    /* 2026-05-30: ketju-paneelin SELKEÄ pystyrakenne — osiot otsikoituna. Korvasi
       yhden ahtaan mega-rivin (käyttäjä: "paljon kaikkea helvetin sekavasti"). */
    /* 2026-06-24 PREMIUM: ketjupalkin navy-otsikko (bleed) + ⚙-ratas asetuksille */
    #chain-bar{border-radius:10px;}
    #chain-bar .cb-head{display:flex;align-items:center;gap:8px;margin:-8px -11px 9px;padding:9px 12px;
      background:#0F1F3A;color:#fff;border-radius:10px 10px 0 0;}
    #chain-bar .cb-head .cb-name{color:#fff;font-weight:500;font-size:12px;}
    #chain-bar .cb-head .cb-name::placeholder{color:#8FA3C0;}
    #chain-bar .cb-head .cb-name:focus{background:rgba(255,255,255,0.10);outline:1px solid rgba(255,255,255,0.30);}
    #chain-bar .cb-head .cb-count{color:#8FA3C0;font-family:ui-monospace,monospace;font-size:11px;font-weight:500;white-space:nowrap;}
    #chain-bar .cb-gear{display:flex;align-items:center;gap:4px;background:transparent;border:0;color:#8FA3C0;font-size:10px;line-height:1;
      padding:4px 6px;cursor:pointer;border-radius:5px;flex:none;}
    #chain-bar .cb-gear:hover{color:#fff;background:rgba(255,255,255,0.10);}
    #chain-bar.cb-settings-open .cb-gear{color:#fff;background:rgba(255,255,255,0.16);}
    /* Valinnaiset tiedot piilossa kunnes otsikon painike avataan. */
    #chain-bar:not(.cb-settings-open) #cb-order-wrap,
    #chain-bar:not(.cb-settings-open) .cb-style-row,
    #chain-bar:not(.cb-settings-open) .cb-optional{display:none !important;}
    #chain-bar .cb-section{margin-top:9px;}
    #chain-bar .cb-slabel{font-size:9.5px;text-transform:uppercase;letter-spacing:0.05em;
      color:var(--text-muted,#64748B);font-weight:700;margin-bottom:4px;}
    #chain-bar .cb-flabel{font-size:11px;color:var(--text-muted,#64748B);width:46px;flex:none;}
    #chain-bar .cb-wide{flex:1;width:auto;}
    /* Segmentoitu 3-tapavalitsin: Klikkaa · Neliö · Lasso */
    #chain-bar .cb-seg-wrap{display:flex;border:1px solid var(--border,#E8EDF3);border-radius: var(--radius-lg);overflow:hidden;}
    #chain-bar .cb-seg{flex:1;padding:7px 4px;font-size:11.5px;font-weight:700;background:var(--panel);
      border:none;border-right:1px solid var(--border,#E8EDF3);cursor:pointer;color:var(--text,#0F1F3A);
      font-family:inherit;white-space:nowrap;}
    #chain-bar .cb-seg:last-child{border-right:none;}
    #chain-bar .cb-seg.active{background:var(--blue,#0F9ED5);color:#fff;}
    #chain-bar .cb-seg:hover:not(.active){background:var(--bg,#FAFAF7);}
    /* Järjestys-alivalitsin (riveittäin · veto · lyhin) — kompaktimpi kuin pää-segmentti */
    #chain-bar .cb-oseg{flex:1;padding:5px 3px;font-size:10.5px;font-weight:700;background:var(--panel);
      border:none;border-right:1px solid var(--border,#E8EDF3);cursor:pointer;color:var(--text,#0F1F3A);
      font-family:inherit;white-space:nowrap;}
    #chain-bar .cb-oseg:last-child{border-right:none;}
    #chain-bar .cb-oseg.active{background:var(--orange,#0F1F3A);color:#fff;}
    #chain-bar .cb-oseg:hover:not(.active){background:var(--bg,#FAFAF7);}
    #chain-bar .cb-osub{font-size:10px;color:var(--muted,#7A8AA0);margin:5px 2px 1px;}
    #chain-bar .cb-straighten{width:100%;margin-top:7px;padding:7px 8px;font-size:11.5px;font-weight:700;
      background:var(--orange,#0F1F3A);color:#fff;border:none;border-radius:var(--radius-lg);cursor:pointer;font-family:inherit;}
    #chain-bar .cb-straighten:hover{filter:brightness(1.06);}
    #chain-bar .cb-straighten:active{transform:translateY(1px);}
    #chain-bar .cb-products{width:100%;margin-top:6px;padding:6px 8px;text-align:left;border:1px solid var(--border,#E8EDF3);
      border-radius:8px;background:var(--panel);color:var(--text,#0F1F3A);font:600 11.5px inherit;cursor:pointer;}
    #chain-bar .cb-products:hover{background:var(--bg,#FAFAF7);}
    #chain-bar .cb-feedback{min-height:16px;margin-top:6px;padding:5px 7px;border-radius:7px;background:var(--bg,#FAFAF7);
      color:var(--text-muted,#64748B);font-size:10.5px;line-height:1.35;}
    #chain-bar .cb-feedback.ok{background:var(--success-feedback-bg,#DCFCE7);color:var(--success-feedback-fg,#166534);}
    #chain-bar .cb-feedback.warn{background:var(--warn-feedback-bg,#FEF3C7);color:var(--warn-feedback-fg,#92400E);}
    #chain-bar .cb-check{display:flex;align-items:center;gap:5px;cursor:pointer;font-size:11.5px;
      margin-top:6px;color:var(--text,#0F1F3A);}
    #chain-bar .cb-check input{cursor:pointer;flex:none;}
    #chain-bar .cb-val{width:64px;padding:3px 6px;border:1px solid var(--border,#E8EDF3);border-radius:7px;font-size:12.5px;}
    #chain-bar .cb-val:disabled{opacity:0.45;}
    #chain-bar .cb-qbtn,#chain-bar .cb-mode,#chain-bar .cb-act{border:1px solid var(--border,#E8EDF3);
      background:var(--btn-sec-bg,#F1F5F9);color:var(--btn-sec-fg,#475569);border-radius:7px;
      padding:3px 8px;font-size:12px;cursor:pointer;font-weight:600;}
    #chain-bar .cb-qbtn.active{background:var(--blue,#0F9ED5);color:#fff;border-color:var(--blue,#0F9ED5);}
    #chain-bar .cb-act.primary{background:var(--btn-bg,#DBE5F0);color:var(--btn-fg,#1E2F4A);border-color:var(--btn-bg,#DBE5F0);}
    #chain-bar .cb-count{font-weight:800;font-family:ui-monospace,monospace;font-size:13px;color:var(--blue,#0F9ED5);white-space:nowrap;}
    #chain-bar .cb-hint{font-size:11px;color:var(--text-muted,#64748B);width:100%;margin-top:3px;}
    /* 2026-07-02: ketjuttamattomat-laskuri + orpo-jäsenten varoitus (symboli poistettu/muuttunut) */
    #chain-bar .cb-unchained{margin-top:5px;font-size:10.5px;font-weight:700;color:#92400e;background:#FEF3C7;border-radius:6px;padding:3px 7px;line-height:1.4;}
    #chain-bar .cb-orphan-warn{display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:10.5px;font-weight:700;color:#B42318;background:#FEE4E2;border-radius:6px;padding:3px 7px;}
    #chain-bar .cb-orphan-warn .cb-mbtn{visibility:visible;margin-left:auto;color:#B42318;border-color:#B42318;}
    #chain-bar .cb-mrow.cb-orphan .cb-mlabel{color:var(--error,#DC2626);text-decoration:line-through;}
    #chain-bar .cb-list{display:flex;flex-wrap:wrap;gap:5px;margin-top:7px;max-height:88px;overflow:auto;}
    #chain-bar .cb-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 7px;border-radius:999px;
      border:1px solid var(--border,#E8EDF3);background:var(--bg,#FAFAF7);font-size:11.5px;cursor:pointer;}
    #chain-bar .cb-pill.active{outline:2px solid var(--blue,#0F9ED5);background:var(--panel);}
    #chain-bar .cb-pill-dot{width:11px;height:11px;border-radius:50%;flex:none;}
    #chain-bar .cb-pill-x{color:var(--text-muted,#64748B);font-weight:700;padding:0 1px;margin-left:1px;}
    #chain-bar .cb-pill-x:hover{color:var(--error,#DC2626);}
    #chain-layer .ch-chip{pointer-events:auto;cursor:pointer;}
    #chain-layer .ch-endbox{pointer-events:auto;cursor:pointer;}
    #chain-layer .ch-cable{pointer-events:auto;cursor:pointer;}
    /* 2026-06-11b: K-ketjun viiva klikattavaksi (avaa paneelin) + hover-glow */
    /* stroke-width CSS-varista → loitonnettaessa hit-alue kasvaa SVG-yksiköissä (ruutu-px pysyy ~vakiona) */
    #chain-layer .ch-line-hit{pointer-events:stroke;cursor:pointer;stroke-width:var(--vk-hitw,14px);}
    #chain-layer .ch-cable-g:hover{filter:drop-shadow(0 0 4px rgba(21,101,192,0.85));}
    /* 2026-06-11b siivous: jäsenrivin toissijaiset napit näkyviin vasta rivin hoverilla */
    #chain-bar .cb-mrow .cb-mbtn{visibility:hidden;}
    #chain-bar:not(.cb-settings-open) .cb-mval{display:none;}
    #chain-bar .cb-mrow:hover .cb-mbtn, #chain-bar .cb-mrow.arm .cb-mbtn{visibility:visible;}
    #chain-bar .cb-members{margin-top:7px;max-height:158px;overflow:auto;border-top:1px dashed var(--border,#E8EDF3);padding-top:6px;}
    #chain-bar .cb-mtitle{font-size:10.5px;color:var(--text-muted,#64748B);margin-bottom:4px;}
    #chain-bar .cb-mrow{display:flex;align-items:center;gap:6px;padding:2px 3px;border-radius: var(--radius-md);font-size:11.5px;}
    #chain-bar .cb-mrow:hover{background:var(--bg,#FAFAF7);}
    #chain-bar .cb-mrow.arm{outline:1.5px dashed var(--blue,#0F9ED5);outline-offset:-1px;}
    #chain-bar .cb-mi{font-family:ui-monospace,monospace;color:var(--text-muted,#64748B);width:16px;text-align:right;flex:none;}
    #chain-bar .cb-mlabel{flex:1;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:60px;}
    #chain-bar .cb-mlabel:hover{color:var(--blue,#0F9ED5);text-decoration:underline;}
    #chain-bar .cb-mval{min-width:34px;text-align:center;cursor:pointer;color:var(--btn-fg,#1E2F4A);font-weight:700;background:var(--btn-sec-bg,#F1F5F9);border-radius:5px;padding:1px 5px;flex:none;}
    #chain-bar .cb-mbtn{border:1px solid var(--border,#E8EDF3);background:var(--panel);border-radius:5px;padding:1px 5px;font-size:11px;cursor:pointer;line-height:1.35;flex:none;}
    #chain-bar .cb-mbtn:disabled{opacity:0.35;cursor:default;}
    #chain-bar .cb-mbtn.cb-mdel:hover{color:var(--error,#DC2626);border-color:var(--error,#DC2626);}
    /* Ketjut-osio 📊 Yhteenveto-ikkunassa */
    #quantities-table-wrap .qm-chains-table{margin-top:6px;border-collapse:collapse;width:auto;font-size:12px;}
    #quantities-table-wrap .qm-chains-table th,#quantities-table-wrap .qm-chains-table td{
      border:1px solid var(--border,#E8EDF3);padding:4px 9px;position:static;background:var(--panel);}
    #quantities-table-wrap .qm-chains-table th{background:var(--navy);color:#fff;font-weight:700;}
    /* 2026-06-28: ketju-symbolierittely — laajennusnuoli per linja + koottu summa */
    #quantities-table-wrap .qm-ch-toggle{cursor:pointer;text-align:center;width:22px;user-select:none;}
    #quantities-table-wrap .qm-ch-caret{display:inline-block;font-size:10px;color:var(--text-muted,#64748B);}
    #quantities-table-wrap .qm-ch-detail td{background:var(--bg,#FAFAF7);font-size:11px;color:var(--text-muted,#64748B);}
    #quantities-table-wrap .qm-ch-summary{margin-top:8px;}
    #quantities-table-wrap .qm-ch-sumbtn{background:none;border:none;cursor:pointer;font:inherit;font-weight:700;font-size:13px;color:var(--text,#0F1F3A);padding:4px 0;display:inline-flex;align-items:center;gap:5px;}
    #quantities-table-wrap .qm-ch-sumbody{font-size:12px;color:var(--text-muted,#64748B);padding:4px 0 0 18px;}
    /* 2026-06-19 V2: näytteenrajaus-tila + sample-paneeli (#ml-sample-panel, peilaa #ml-panel) */
    body.ml-sample-on #viewport-wrap, body.ml-sample-on #page-img{cursor:crosshair;}
    #ml-sample-panel{position:fixed;right:10px;top:98px;z-index:142;width:280px;max-width:calc(100vw - 16px);
      background:var(--panel,#fff);border:1px solid #DDE3EC;border-radius:10px;
      box-shadow:0 8px 24px rgba(15,31,58,.14);font-size:12.5px;color:var(--text,#0F1F3A);
      max-height:calc(100vh - 175px);overflow-y:auto;overscroll-behavior:contain;}
    #ml-line-modal{ position:fixed; inset:0; z-index:9000; display:flex;
    align-items:center; justify-content:center; background:rgba(15,31,58,0.45); }
  #ml-line-modal .mlm-card{ background:var(--panel); border-radius:14px;
    width:96vw; max-width:1680px; height:94vh; max-height:94vh;
    overflow:hidden; display:flex; flex-direction:column;
    box-shadow:0 18px 50px rgba(0,0,0,0.35); }
  #ml-line-modal .mlm-head{ background:#0F1F3A; color:#fff; padding:11px 16px;
    font-weight:600; letter-spacing:.01em; display:flex; justify-content:space-between; align-items:center; }
  #ml-line-modal .mlm-body{ padding:14px 16px; overflow:hidden; flex:1 1 auto; min-height:0;
    display:flex; flex-direction:column; }
  /* 2026-06-22: SVG koko asetetaan JS:ssä px:nä (sc = lyhyen ulottuvuuden mukaan) →
     pitkä ohut hylly EI enää kutistu sirpaleeksi; pitkä akseli vierittyy. */
  #ml-line-modal .mlm-zoombar{ display:flex; align-items:center; gap:6px; margin:0 0 6px; font-size:12px; color:var(--text-muted); }
  #ml-line-modal .mlm-zoombar button{ padding:3px 9px; font-weight:700; }
  #ml-line-modal .mlm-zoombar #mlm-zoom-lbl{ min-width:46px; text-align:center; font-family:monospace; color:var(--text); }
  #ml-line-modal .mlm-svg-wrap{ overflow:auto; flex:1 1 auto; min-height:140px; max-height:none;
    background:#0F1F3A; border-radius:8px; }
  #ml-line-modal svg{ background:#0F1F3A; border-radius:8px; display:block; }
  #ml-line-modal .mlm-seg{ stroke:#5EA0FF; stroke-width:3; }
  #ml-line-modal .mlm-seg.mlm-off{ stroke:#8FA3C0; stroke-width:2; stroke-opacity:0.5; }
  #ml-line-modal .mlm-hit{ stroke:transparent; stroke-width:14; cursor:pointer; }
  #ml-line-modal .mlm-cats{ display:flex; align-items:center; gap:14px; font-size:13px; font-weight:600;
    background:var(--bg); border:1px solid var(--border); border-radius:9px; padding:8px 11px; }
  #ml-line-modal .mlm-cats-lbl{ color:var(--text-muted); font-weight:700; }
  #ml-line-modal .mlm-cats label{ display:flex; align-items:center; gap:5px; cursor:pointer; }
  #ml-line-modal .mlm-meter{ font-size:13px; font-weight:700; font-family:ui-monospace,monospace;
    color:var(--text); margin:10px 0 4px; }
  #ml-line-modal .mlm-tools{ display:flex; gap:8px; flex-wrap:wrap; margin:8px 0 2px; }
  /* legenda: värisaurat selittävät sininen=mukaan / punainen=pois (ei lihavoitua tekstiä) */
  #ml-line-modal .mlm-legend{ display:flex; align-items:center; flex-wrap:wrap; gap:6px 14px; margin:9px 0 2px; }
  #ml-line-modal .mlm-leg{ display:inline-flex; align-items:center; gap:6px; font-size:12px; font-weight:600; color:var(--text); }
  #ml-line-modal .mlm-leg-sw{ width:13px; height:13px; border-radius:4px; }
  #ml-line-modal .mlm-leg-on{ background:#5EA0FF; }
  #ml-line-modal .mlm-leg-off{ background:#8FA3C0; opacity:0.7; }
  #ml-line-modal .mlm-leg-tip{ flex:1 0 100%; font-size:11px; color:var(--text-muted); }
  #ml-line-modal .mlm-foot{ display:flex; gap:8px; padding:12px 16px; border-top:1px solid var(--border); }
  #ml-line-modal button{ font-family:inherit; border:1px solid var(--border); border-radius:9px;
    padding:8px 12px; background:var(--btn-sec-bg); color:var(--btn-sec-fg); cursor:pointer; }
  #ml-line-modal button.mlm-primary{ background:var(--btn-bg); color:var(--btn-fg); border-color:transparent; font-weight:700;
    box-shadow:0 1px 2px rgba(15,31,58,0.12); }
  #ml-line-modal button.mlm-primary:hover{ background:var(--btn-bg-hover,#C2D2E5); }
  #ml-line-modal button.mlm-grow{ flex:1; }
  /* yksi selkeä päätoiminto: Etsi hallitsee, Mittaa kevyempi sekundääri */
  #ml-line-modal button.mlm-find{ flex:2; font-size:14px; padding:10px 12px; }
  #ml-line-modal button.mlm-measure{ flex:1; background:transparent; color:var(--bark-warm,#64748B); font-weight:600; }
  #ml-line-modal button.mlm-measure:hover{ background:var(--bg,#FAFAF7); color:var(--text); }
  /* 2026-06-24 REITIT: segmentoitu Putki/Hylly + ammattimainen valintapalkki + piilota muut */
  #ml-line-modal .mlm-cats{ background:transparent; border:none; padding:0; gap:0; }
  #ml-line-modal .mlm-seg-ctrl{ display:inline-flex; background:var(--btn-sec-bg,#F1F5F9); border-radius:9px; padding:3px; gap:3px; }
  #ml-line-modal .mlm-seg-ctrl label{ display:flex; align-items:center; gap:6px; font-size:13px; font-weight:600; color:var(--btn-sec-fg,#475569); padding:6px 16px; border-radius:7px; cursor:pointer; }
  #ml-line-modal .mlm-seg-ctrl label input{ display:none; }
  #ml-line-modal .mlm-seg-ctrl label:has(input:checked){ background:var(--panel,#fff); color:var(--btn-fg,#1E2F4A); box-shadow:0 1px 2px rgba(15,31,58,0.10); }
  #ml-line-modal .mlm-tool{ display:inline-flex; align-items:center; gap:6px; font-size:12.5px; font-weight:600; padding:6px 11px; background:var(--panel,#fff); border:1px solid var(--border); color:var(--btn-sec-fg,#475569); border-radius:8px; cursor:pointer; }
  #ml-line-modal .mlm-tool:hover{ background:var(--bg,#FAFAF7); border-color:var(--bark-warm,#64748B); }
  #ml-line-modal .mlm-tool.mlm-tool-on{ background:var(--btn-bg,#DBE5F0); color:var(--btn-fg,#1E2F4A); border-color:transparent; }
  #ml-line-modal .mlm-tool svg{ width:15px; height:15px; flex:0 0 auto; }
  #ml-line-modal #mlm-svg.mlm-hideoff .mlm-off{ display:none; }
  #ml-line-modal .mlm-hinttip{ font-size:11px; color:var(--text-muted); margin:2px 0 0; }
  #ml-line-modal button.mlm-manual{ flex:1; background:transparent; color:var(--bark-warm,#64748B); font-weight:600; }
  #ml-line-modal button.mlm-manual:hover{ background:var(--bg,#FAFAF7); color:var(--text); }
    #ml-sample-panel .mls-head{display:flex;align-items:center;justify-content:space-between;gap:8px;font-weight:500;letter-spacing:.01em;
      padding:8px 12px;background:#0F1F3A;color:#fff;border-radius:10px 10px 0 0;}
    #ml-sample-panel .mls-scale{font-size:11px;font-weight:700;letter-spacing:0.02em;background:rgba(255,255,255,0.22);
      border:1px solid rgba(255,255,255,0.5);padding:4px 10px;border-radius:8px;cursor:pointer;white-space:nowrap;}
    #ml-sample-panel .mls-scale:hover{background:rgba(255,255,255,0.35);}
    #ml-sample-panel .mls-body{padding:14px 15px;}
    /* Hero-tuloskortti: metri-luku on YKSI selkeä fokus (frontend-design hierarkia) */
    #ml-sample-panel .mls-result{background:var(--bg,#FAFAF7);
      border:1px solid var(--border,#E8EDF3);border-radius:11px;padding:11px 12px;margin-bottom:12px;}
    #ml-sample-panel .mls-fp{font-size:11.5px;line-height:1.5;color:var(--text-muted,#64748B);
      background:var(--bg,#FAFAF7);border:1px solid var(--border,#E8EDF3);border-radius:9px;padding:7px 9px;margin-bottom:9px;}
    #ml-sample-panel .mls-fp strong{color:var(--text,#0F1F3A);}
    #ml-sample-panel .mls-total{display:flex;align-items:baseline;gap:9px;font-size:27px;font-weight:800;
      font-family:ui-monospace,monospace;line-height:1.05;letter-spacing:-0.01em;margin:2px 0 4px;}
    #ml-sample-panel .mls-result .mls-sub{margin:0;}
    #ml-sample-panel .mls-sw{width:14px;height:14px;border-radius:4px;flex:none;align-self:center;box-shadow:0 0 0 1px rgba(0,0,0,0.15);}
    #ml-sample-panel .mls-half-note{font-size:9.5px;font-weight:700;color:var(--text-muted,#64748B);
      background:var(--bg,#FAFAF7);border:1px solid var(--border,#E8EDF3);border-radius:5px;padding:0 4px;}
    #ml-sample-panel .mls-cats{display:flex;gap:16px;margin-bottom:8px;}
    #ml-sample-panel .mls-cats label{display:flex;align-items:center;gap:6px;cursor:pointer;font-weight:600;}
    #ml-sample-panel .mls-check{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;
      cursor:pointer;margin-bottom:8px;}
    #ml-sample-panel .mls-check input{margin:0;}
    #ml-sample-panel .mls-slrow{margin-bottom:8px;}
    #ml-sample-panel .mls-slrow label{display:flex;justify-content:space-between;align-items:center;
      font-size:11px;color:var(--text-muted,#64748B);font-weight:600;margin-bottom:3px;}
    #ml-sample-panel .mls-slrow #mls-tol-val{font-family:ui-monospace,monospace;color:var(--text,#0F1F3A);}
    #ml-sample-panel .mls-slrow input[type=range]{width:100%;}
    #ml-sample-panel .mls-name{width:100%;box-sizing:border-box;border:1px solid var(--border,#E8EDF3);
      border-radius:8px;padding:7px 9px;font-size:12.5px;font-family:inherit;margin-bottom:9px;}
    #ml-sample-panel .mls-btn{border:1px solid var(--border,#E8EDF3);background:var(--btn-sec-bg,#F1F5F9);
      color:var(--btn-sec-fg,#475569);border-radius:8px;padding:7px 11px;font-size:12.5px;font-weight:700;
      cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;justify-content:center;gap:6px;}
    #ml-sample-panel .mls-btn svg{width:14px;height:14px;flex:0 0 auto;}
    #ml-sample-panel .mls-btn:hover{filter:brightness(0.97);}
    #ml-sample-panel .mls-primary{display:flex;width:100%;background:var(--btn-bg,#DBE5F0);
      color:var(--btn-fg,#1E2F4A);border-color:transparent;padding:11px;font-size:13.5px;border-radius:10px;
      box-shadow:0 1px 2px rgba(15,31,58,0.10);}
    #ml-sample-panel .mls-primary:hover{background:var(--btn-bg-hover,#C2D2E5);}
    /* sekundäärit kevyemmät kuin pää-CTA → yksi selkeä päätoiminto */
    #ml-sample-panel .mls-rowbtns .mls-btn{background:transparent;border-color:var(--border,#E8EDF3);
      color:var(--bark-warm,#64748B);font-weight:600;}
    #ml-sample-panel .mls-rowbtns .mls-btn:hover{background:var(--bg,#FAFAF7);color:var(--text,#0F1F3A);}
    #ml-sample-panel .mls-foot{display:flex;gap:7px;margin-top:12px;padding-top:10px;border-top:1px solid var(--border,#E8EDF3);}
    #ml-sample-panel .mls-foot .mls-btn{background:transparent;color:var(--text-muted,#94A3B8);font-weight:600;border-color:transparent;}
    #ml-sample-panel .mls-foot .mls-btn:hover{background:var(--bg,#FAFAF7);color:var(--text,#0F1F3A);}
    #ml-sample-panel .mls-foot .mls-btn{flex:1;}
    #ml-sample-panel .mls-acc{margin-top:11px;padding-top:8px;border-top:1px solid var(--border,#E8EDF3);}
    #ml-sample-panel .mls-acc-head{font-size:9.5px;text-transform:uppercase;letter-spacing:0.05em;
      color:var(--text-muted,#64748B);font-weight:700;margin-bottom:5px;}
    #ml-sample-panel .mls-acc-row{display:flex;align-items:center;gap:7px;padding:2px 0;}
    #ml-sample-panel .mls-acc-sw{width:12px;height:12px;border-radius:3px;flex:none;box-shadow:0 0 0 1px rgba(0,0,0,0.15);}
    #ml-sample-panel .mls-acc-name{font-weight:700;font-family:ui-monospace,monospace;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
    #ml-sample-panel .mls-acc-m{font-family:ui-monospace,monospace;}
    #ml-sample-panel .mls-acc-total{margin-top:6px;padding-top:6px;border-top:1px solid var(--border,#E8EDF3);font-size:12.5px;}
    /* TASO 1: segmentoitu Putki/Hylly-valitsin (ei enää toista radio-blokkia) */
    #ml-sample-panel .mls-seg{display:flex;gap:2px;background:var(--bg,#FAFAF7);border:1px solid var(--border,#E8EDF3);
      border-radius:9px;padding:3px;margin-bottom:10px;}
    #ml-sample-panel .mls-seg-btn{flex:1;border:0;background:transparent;color:var(--text-muted,#64748B);
      font-family:inherit;font-size:12.5px;font-weight:700;padding:6px 8px;border-radius:7px;cursor:pointer;}
    #ml-sample-panel .mls-seg-btn.on{background:var(--btn-bg,#DBE5F0);color:var(--btn-fg,#1E2F4A);
      box-shadow:0 1px 2px rgba(15,31,58,0.10);}
    /* tyyppirivi nyt hero-kortin SISÄLLÄ → kevyt, ei omaa laatikkoa */
    #ml-sample-panel .mls-tube{font-size:10px;font-weight:700;letter-spacing:0.04em;text-transform:uppercase;
      color:var(--bark-warm,#64748B);margin:0 0 2px;}
    #ml-sample-panel .mls-tube strong{font-weight:800;color:var(--text,#0F1F3A);}
    #ml-sample-panel .mls-sub{font-size:11.5px;color:var(--text-muted,#64748B);margin:-2px 0 10px;}
    #ml-sample-panel .mls-sub strong{color:var(--text,#0F1F3A);font-family:ui-monospace,monospace;}
    #ml-sample-panel .mls-wchip{background:var(--bg,#FAFAF7);border:1px solid var(--border,#E8EDF3);
      border-radius:5px;padding:0 5px;font-weight:700;color:var(--text,#0F1F3A);}
    /* Tasovalitsin (2026-06-24): hyllyn CAD-taso — vaihto lukitsee haun oikeaan tasoon */
    #ml-sample-panel .mls-layerpick{display:flex;align-items:center;gap:7px;margin:2px 0 10px;
      background:var(--bg,#FAFAF7);border:1px solid var(--border,#E8EDF3);border-radius:8px;padding:6px 8px;}
    #ml-sample-panel .mls-lp-lbl{font-size:10px;font-weight:700;letter-spacing:0.03em;text-transform:uppercase;
      color:var(--bark-warm,#64748B);white-space:nowrap;}
    #ml-sample-panel #mls-layer-pick{flex:1;min-width:0;font-size:11.5px;font-family:ui-monospace,monospace;
      color:var(--text,#0F1F3A);background:var(--panel,#fff);border:1px solid var(--border,#E8EDF3);border-radius:6px;
      padding:4px 6px;cursor:pointer;}
    /* P3: ylimatchaus-varoitus */
    #ml-sample-panel .mls-warn{background:#FEF6E7;border:1px solid #F2C94C;color:#8A6D1A;font-size:11px;
      line-height:1.45;border-radius:8px;padding:7px 9px;margin-bottom:10px;}
    /* TASO 3: lisäasetusten avaaja */
    #ml-sample-panel .mls-adv-toggle{display:block;width:100%;text-align:left;border:0;background:transparent;
      color:var(--text-muted,#64748B);font-family:inherit;font-size:11.5px;font-weight:700;cursor:pointer;
      padding:8px 2px 4px;}
    #ml-sample-panel .mls-adv-toggle:hover{color:var(--text,#0F1F3A);}
    #ml-sample-panel .mls-adv-caret{display:inline-block;width:11px;color:var(--text-muted,#94A3B8);}
    #ml-sample-panel .mls-adv{padding:4px 0 2px;border-top:1px solid var(--border,#E8EDF3);margin-top:2px;}
    #ml-sample-panel .mls-check.mls-dis{opacity:0.5;cursor:default;}
    #ml-sample-panel .mls-manual-btn{display:block;width:100%;margin-top:6px;}
    #ml-sample-panel .mls-rowbtns{display:flex;gap:7px;margin-top:6px;}
    #ml-sample-panel .mls-rowbtns .mls-btn{flex:1;font-size:11.5px;padding:7px 6px;}
    #ml-sample-panel .mls-btn.mls-active{background:#FDE8E8;border-color:#dc2626;color:#b91c1c;}
    #ml-sample-panel .mls-acc-add{margin-left:auto;border:1px solid var(--border,#E8EDF3);background:var(--btn-sec-bg,#F1F5F9);
      color:var(--btn-sec-fg,#475569);border-radius:6px;padding:1px 7px;font-size:10.5px;font-weight:700;cursor:pointer;font-family:inherit;}
    #ml-sample-panel .mls-acc-add:hover{background:var(--btn-bg,#DBE5F0);color:var(--btn-fg,#1E2F4A);}
    body.ml-manual-on, body.ml-manual-on #viewport-wrap{cursor:crosshair;}
    body.ml-areadel-on, body.ml-areadel-on #viewport-wrap{cursor:crosshair;}
    #ml-cursor-tip{position:fixed;z-index:99999;pointer-events:none;background:#0F1F3A;color:#fff;
      font-size:12px;font-weight:700;font-family:ui-monospace,monospace;padding:3px 8px;border-radius:6px;
      box-shadow:0 4px 12px rgba(0,0,0,0.3);white-space:nowrap;display:none;}

  #draw-ctx-menu .ctx-w-btn {
    background: #fafafa; border: 1px solid var(--border); border-radius: 5px;
    padding: 5px 7px; font-size: 11px; font-weight: 600; cursor: pointer;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    color: var(--text); flex: 1 1 calc(33% - 3px); min-width: 50px;
    display: flex; align-items: center; justify-content: space-between; gap: 4px;
  }
  #draw-ctx-menu .ctx-w-btn:hover { background: #eef3fb; border-color: var(--blue); color: var(--blue); }
  #draw-ctx-menu .ctx-w-btn.active { background: rgba(15,158,213,0.12); border-color: var(--blue); color: var(--blue); }
  #draw-ctx-menu .ctx-w-btn kbd {
    font-size: 9px; padding: 0 3px; background: rgba(0,0,0,0.06);
    border-radius: 2px; color: var(--text-muted);
  }

  .ctx-item {
    display:block; width:100%; padding:7px 10px; background:none; border:none;
    text-align:left; font-size:13px; color:var(--text); cursor:pointer; border-radius: var(--radius-md);
    font-family:inherit; letter-spacing:-0.01em; transition:background 0.08s;
  }
  /* 2026-08-01 (käyttäjärepro "rivi kokonaan musta"): tausta+väri AINA parina —
     graphitessa --btn-bg on #1D1D1F, joten pelkkä tausta teki mustan rivin jolla
     tumma teksti. Hoveriin SEKUNDÄÄRIPARI (graphite #F0F0F2/#5C5C61 = kevyt
     vaalea, sama henki kuin tumman teeman --gf-accent-soft) — primääripari
     olisi tehnyt raskaan mustan palkin. theme-darkin oma korkeamman
     spesifisyyden sääntö (01-base-12) voittaa yhä. */
  .ctx-item:hover { background:var(--btn-sec-bg,#DBE5F0); color:var(--btn-sec-fg,var(--text)); }
  .ctx-item-danger { color:#dc2626; }
  /* color pakollinen: .ctx-item:hover (0,2,0) voittaisi muuten .ctx-item-dangerin (0,1,0) */
  .ctx-item-danger:hover { background:#fee2e2; color:#dc2626; }

  /* 2026-06-27: oma symboli -kustannusstatus — pallo symbolikorteissa + tyhjä vihje piiloon */
  .sp-card { position: relative; }
  .sp-card .sp-rek { position:absolute; top:4px; left:5px; font-size:11px; line-height:1; z-index:2; pointer-events:none; }
  .sp-card .sp-rek-ok { color: var(--success,#16A34A); }
  .sp-card .sp-rek-empty { color: var(--warning,#D97706); }
  .sp-card .sp-rek-none { color: var(--text-faint,#9A9AA0); }
  #stamp-picker-cost-hint:empty { display:none; }

  #stamp-picker-grid .sp-card {
    background:var(--panel);
    border:1.5px solid var(--border);
    border-radius:7px;
    padding:6px 4px;
    cursor:pointer;
    display:flex;
    flex-direction:column;
    align-items:center;
    gap:4px;
    transition: border-color 0.12s ease, background 0.12s ease, transform 0.08s ease;
    min-height:90px;
    position:relative;
  }
  #stamp-picker-grid .sp-card:hover {
    border-color: var(--btn-bg);
    background: #F8FAFC;
    transform: translateY(-1px);
  }
  #stamp-picker-grid .sp-card.selected {
    border-color: #0066DC;
    border-width: 2px;
    background: #EFF6FF;
    box-shadow: 0 0 0 3px rgba(0,102,220,0.12);
  }
  #stamp-picker-grid .sp-thumb {
    width:64px;
    height:64px;
    display:flex;
    align-items:center;
    justify-content:center;
    overflow:hidden;
  }
  #stamp-picker-grid .sp-thumb img,
  #stamp-picker-grid .sp-thumb svg {
    width:100%;
    height:100%;
    object-fit:contain;
  }
  #stamp-picker-grid .sp-name {
    font-size:10.5px;
    font-weight:600;
    color: var(--text);
    text-align:center;
    line-height:1.2;
    overflow:hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break:break-word;
  }
  #stamp-picker-grid .sp-kind-tag {
    font-size:9px;
    color: var(--text-muted);
    text-transform:uppercase;
    letter-spacing:0.04em;
    font-weight:700;
  }
  #stamp-picker-grid .sp-section-title {
    grid-column: 1 / -1;
    font-size:10px;
    font-weight:700;
    color: var(--text-muted);
    text-transform:uppercase;
    letter-spacing:0.07em;
    padding: 8px 4px 4px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 2px;
  }
  #stamp-picker-grid .sp-section-title:first-child {
    padding-top: 0;
  }
  #stamp-picker-grid .sp-fav-btn {
    position:absolute; top:2px; right:3px; z-index:2;
    background:transparent; border:0; cursor:pointer;
    font-size:14px; line-height:1; padding:1px 3px;
    color: var(--text-muted); opacity:0; transition:opacity .12s, color .12s;
  }
  #stamp-picker-grid .sp-card:hover .sp-fav-btn,
  #stamp-picker-grid .sp-card.favorite .sp-fav-btn { opacity:1; }
  #stamp-picker-grid .sp-card.favorite .sp-fav-btn { color:#F5A623; }
  #stamp-picker-color-grid button {
    aspect-ratio: 1;
    border-radius: 3px;
    border: 1px solid rgba(0,0,0,0.08);
    cursor: pointer;
    padding: 0;
  }
  #stamp-picker-color-grid button.selected {
    border: 2px solid #0F1F3A;
    transform: scale(1.05);
  }
  #stamp-picker-start:not([disabled]) {
    opacity: 1;
  }
  #stamp-picker-start:not([disabled]):hover {
    background: var(--btn-bg-hover);
  }

@keyframes prep-spin { to { transform: rotate(360deg); } }
@keyframes prep-fadein { from { opacity: 0; } to { opacity: 1; } }
@keyframes prep-pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }
.kbd-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; color: #444; font-size: 12.5px; }
.kbd-row kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px;
  background: linear-gradient(180deg, #fafafa, #ececec);
  border: 1px solid #ccc; border-bottom-width: 2px;
  border-radius: 5px; font-family: 'JetBrains Mono', monospace;
  font-size: 11px; font-weight: 600; color: #333;
  box-shadow: 0 1px 0 rgba(0,0,0,0.04);
}
#kbd-help-fab {
  position: fixed; bottom: 18px; right: 18px;
  width: 36px; height: 36px; border-radius: 50%;
  background: rgba(255,255,255,0.95); color: var(--text);
  border: 1px solid var(--border); cursor: pointer;
  font-size: 16px; font-weight: 700;
  box-shadow: 0 2px 10px rgba(0,0,0,0.10);
  display: flex; align-items: center; justify-content: center;
  /* 2026-07-10 motion-auditti: transition:all → eksplisiittiset propertyt
     (hover muuttaa vain taustaa, väriä ja transformia). */
  z-index: 990; transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
#kbd-help-fab:hover { background: var(--blue); color: #fff; transform: scale(1.05); }
body.hub-active #kbd-help-fab { display: none; }

/* ─── PROJECT HUB v2 (2026-07-02) — Countfire-selkeä: projektikortit + projektisivu ─── */
#hub-overlay {
  position: fixed; inset: 0;
  background: var(--bg, #FAFAF7);
  z-index: 1800;
  display: none;
  flex-direction: column;
  overflow-y: auto;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
#hub-overlay.show { display: flex; animation: hubFadeIn 0.18s ease-out; }
@keyframes hubFadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
#hub-header {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 20px 48px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
  position: sticky; top: 0; z-index: 5;
}
/* 2026-07-11 HUB-auditti: min-width:0 antoi brändilohkon KUTISTUA alle sisältönsä →
   flex:none-logo (120px) + nowrap-alaotsikko VUOTIVAT lohkon yli hub-actionsin alle
   (mitattu 407px leveydellä: brand 68px, sub x=154 nappirivin sisällä). flex:none →
   brändi varaa aina oman tilansa; kapeat leveydet hoitaa alla oleva media query. */
#hub-header .hub-brand {
  display: flex; align-items: baseline; gap: 14px; flex: none;
}
#hub-header .hub-logo {
  height: 30px; width: auto; display: block; flex: none;
}
/* 2026-06-28: Hub-logon teksti on kovakoodattu tummaksi (fill="#0F1F3A") → näkymätön tummalla
   Hub-otsikolla. CSS-fill voittaa attribuutin. Vaalea Hub ennallaan (sääntö koskee vain tummaa). */
body.theme-dark #hub-header .hub-logo text { fill: var(--text); }
#hub-header .hub-sub {
  font-size: 13px; color: var(--text-soft);
  font-weight: 600; letter-spacing: 0.01em; white-space: nowrap;
}
#hub-header .hub-actions { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
/* 2026-07-11 HUB-auditti: kapealla ikkunalla header rivittyy siististi kahteen riviin
   (brändi ylös, haku+toiminnot alle koko leveydelle) — ennen elementit menivät päällekkäin. */
@media (max-width: 1120px) {
  #hub-header { flex-wrap: wrap; gap: 10px 14px; }
  #hub-header .hub-actions { flex: 1 1 100%; justify-content: flex-start; }
  #hub-search { flex: 1 1 150px; width: auto; min-width: 120px; }
}
#hub-search {
  padding: 9px 13px; font-size: 13px;
  border: 1px solid var(--border); border-radius: 10px;
  width: 230px; background: var(--bg, #FAFAF7);
  outline: none; transition: border-color 0.12s ease, box-shadow 0.12s ease;
  font-family: inherit; color: var(--text);
}
#hub-search:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(30,47,74,0.10); background: var(--panel); }
#hub-sort {
  padding: 9px 11px; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg, #FAFAF7); cursor: pointer;
  font-family: inherit; color: var(--text-soft); font-weight: 600;
}
.hub-btn {
  background: var(--btn-sec-bg); color: var(--btn-sec-fg);
  border: none; padding: 10px 18px; border-radius: 10px;
  font-size: 13px; font-weight: 700; cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, transform 0.12s ease;
}
.hub-btn:hover { background: #E2E8F0; color: var(--leaf-deep); transform: translateY(-1px); }
.hub-btn:active { transform: translateY(0); }
.hub-btn.primary { background: #0F1F3A; color: #fff; box-shadow: 0 2px 8px rgba(15,31,58,0.20); }
.hub-btn.primary:hover { background: #1E293B; color: #fff; }
body.theme-dark .hub-btn.primary { background: var(--canvas-accent, #1565C0); color: #fff; }
.hub-btn.ghost { background: var(--btn-sec-bg); color: var(--btn-sec-fg); border: 0; }
.hub-btn.ghost:hover { background: #E2E8F0; color: var(--leaf-deep); }

/* 2026-06-30 Hub-prep-portitus (Countfire "Preparing"), 2026-07-02 korttiversio:
   kortti näyttää Valmistellaan N/M ja avaus on estetty kunnes esivalmistelu
   (PNG+vektorit levylle) on valmis → Valmis ✓ */
.hub-card.preparing .hc-thumb::after { content: ''; position: absolute; inset: 0; background: rgba(255,255,255,0.55); z-index: 1; }
body.theme-dark .hub-card.preparing .hc-thumb::after { background: rgba(0,0,0,0.45); }
.hc-prep { display: inline-flex; align-items: center; gap: 7px; font-size: 11.5px; font-weight: 700; color: var(--blue); white-space: nowrap; }
.hc-prep .hp-spin { width: 12px; height: 12px; border: 2px solid var(--border); border-top-color: var(--blue); border-radius: 50%; animation: hp-rot .7s linear infinite; flex: 0 0 auto; }
.hc-prep .hp-bar { width: 64px; height: 4px; border-radius: 3px; background: var(--border); overflow: hidden; flex: 0 0 auto; }
.hc-prep .hp-bar i { display: block; height: 100%; width: 0; background: var(--blue); transition: width .3s; }
.hc-prep.ready { color: #16A34A; }
.hc-prep.ready .hp-spin { display: none; }
.hc-prep.ready .hp-bar i { background: #16A34A; }
@keyframes hp-rot { to { transform: rotate(360deg); } }
/* 2026-06-16: Uusi projekti -ikkunan tiedostopudotus (yhdistetty tuontireitti: nimi + tiedostot samassa) */
#hub-new-drop { margin-top: 5px; border: 2px dashed var(--border); border-radius: 11px; background: var(--bg); padding: 13px; transition: border-color .15s, background .15s; }
#hub-new-drop.drag-over { border-color: var(--blue); background: rgba(15,31,58,0.06); }
#hub-new-drop-empty { display: flex; flex-direction: column; align-items: center; gap: 2px; cursor: pointer; padding: 4px 0; }
#hub-new-drop-empty .hnd-icon { font-size: 21px; opacity: .8; line-height: 1; }
#hub-new-drop-empty .hnd-text { font-size: 13px; font-weight: 600; color: var(--text); }
#hub-new-drop .hnd-link { background: none; border: 0; color: var(--blue); font: inherit; font-size: 12.5px; cursor: pointer; padding: 1px; text-decoration: underline; }
#hub-new-files { display: flex; flex-direction: column; gap: 4px; }
#hub-new-files:not(:empty) { margin-top: 8px; }
.hnf-row { display: flex; align-items: center; gap: 8px; font-size: 12.5px; background: var(--panel); border: 1px solid var(--border); border-radius: 7px; padding: 5px 9px; }
.hnf-row .hnf-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.hnf-row .hnf-del { background: none; border: 0; color: var(--text-muted); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; flex-shrink: 0; }
.hnf-row .hnf-del:hover { color: #DC2626; }

#hub-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 18px;
  align-content: start;
  padding: 26px 48px 56px;
}
#hub-grid[hidden] { display: none; }
/* ── Projektikortti ── */
.hub-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
  display: flex; flex-direction: column;
  position: relative;
  box-shadow: 0 1px 2px rgba(15,31,58,0.05);
  transition: box-shadow .15s ease, transform .12s ease, border-color .15s ease;
}
.hub-card:hover { box-shadow: 0 10px 28px rgba(15,31,58,0.12); transform: translateY(-2px); border-color: #C9D4E3; }
body.theme-dark .hub-card:hover { border-color: rgba(255,255,255,0.22); }
.hub-card:focus-visible { outline: 2px solid var(--canvas-accent, #1565C0); outline-offset: 2px; }
.hc-thumb {
  height: 150px; position: relative; overflow: hidden;
  background: linear-gradient(180deg, #F4F6FA, #E9EDF4);
  border-bottom: 1px solid var(--border);
}
body.theme-dark .hc-thumb { background: rgba(255,255,255,0.04); }
.hc-thumb img {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
  display: block; background: #fff;
}
.hc-thumb-ph {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  color: var(--text-faint, #9A9AA0); font-size: 11.5px; font-weight: 600;
  background-image:
    repeating-linear-gradient(0deg, transparent, transparent 23px, rgba(15,31,58,0.05) 24px),
    repeating-linear-gradient(90deg, transparent, transparent 23px, rgba(15,31,58,0.05) 24px);
}
.hc-thumb-ph .ph-hint { font-size: 10.5px; font-weight: 600; color: var(--text-muted); }
/* 2026-07-11 HUB-auditti — thumbin latausvaihe: EI virhetekstiä ("Ei esikatselua" näkyy
   vasta kun kuva aidosti puuttuu = onerror pudottaa .loading-luokan), tilalla hiljainen
   shimmer. prefers-reduced-motion-yleissääntö (01-base-12.css) pysäyttää shimmerin →
   staattinen himmeä placeholder, ei tekstiä — sekin lukee latauksena, ei virheenä. */
.hc-thumb.loading .hc-thumb-ph span { display: none; }
.hc-thumb.loading .hc-thumb-ph svg { opacity: .45; }
.hc-thumb.loading .hc-thumb-ph::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 32%, rgba(255,255,255,0.6) 50%, transparent 68%);
  transform: translateX(-100%); animation: hc-shimmer 1.4s ease-in-out infinite;
}
body.theme-dark .hc-thumb.loading .hc-thumb-ph::after {
  background: linear-gradient(100deg, transparent 32%, rgba(255,255,255,0.09) 50%, transparent 68%);
}
@keyframes hc-shimmer { to { transform: translateX(100%); } }
/* Tumma teema: thumbit ovat valkoista paperia → kevyt himmennys ettei kortti "loista" */
body.theme-dark .hc-thumb img, body.theme-dark .hd-dwg-thumb img { filter: brightness(.9); }
.hc-actions {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  display: flex; gap: 6px;
  opacity: 0; transition: opacity .15s ease;
}
.hub-card:hover .hc-actions, .hub-card:focus-within .hc-actions { opacity: 1; }
.hc-actions button {
  width: 28px; height: 28px; border-radius: 8px;
  border: 1px solid rgba(15,31,58,0.14);
  background: rgba(255,255,255,0.94);
  color: #334155; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
body.theme-dark .hc-actions button { background: rgba(24,26,31,0.92); color: var(--text-soft); border-color: rgba(255,255,255,0.16); }
.hc-actions button:hover { color: var(--blue); border-color: var(--blue); }
.hc-actions button.del:hover { color: #DC2626; border-color: #DC2626; background: #FEF2F2; }
.hc-actions svg { stroke: currentColor; }
.hc-body { padding: 13px 16px 10px; display: flex; flex-direction: column; gap: 5px; flex: 1; }
.hc-name {
  font-size: 15px; font-weight: 700; color: var(--text);
  letter-spacing: -0.01em; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hc-sub {
  font-size: 12px; color: var(--text-soft);
  display: flex; gap: 9px; align-items: center; min-height: 15px;
  white-space: nowrap; overflow: hidden;
}
.hc-sub .hc-no { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11px; color: var(--text-muted); flex: none; }
.hc-sub .hc-cust { overflow: hidden; text-overflow: ellipsis; }
.hc-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 3px; }
.hc-chip {
  font-size: 11px; font-weight: 600; color: var(--text-soft);
  background: var(--btn-sec-bg, #F1F5F9); border: 1px solid var(--border);
  border-radius: 99px; padding: 2px 9px; white-space: nowrap;
}
.hc-chip.designer { color: var(--blue); }
body.theme-dark .hc-chip { background: rgba(255,255,255,0.06); }
.hc-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 16px 11px;
  border-top: 1px dashed var(--border);
  font-size: 11.5px; color: var(--text-soft);
}
.hc-status { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; min-height: 16px; }
.hc-status .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-faint); flex: none; }
.hc-status.active { color: #15803D; }
.hc-status.active .dot { background: #16A34A; }
.hc-status.idle { color: #B45309; }
.hc-status.idle .dot { background: #F59E0B; }
.hc-status.old { color: var(--text-muted); }
.hc-date { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text-muted); }
/* Uusi projekti -kortti */
.hub-card.new {
  border: 2px dashed var(--border); background: transparent; box-shadow: none;
  align-items: center; justify-content: center; min-height: 262px;
  color: var(--text-soft);
}
.hub-card.new:hover { border-color: var(--blue); color: var(--blue); transform: none; box-shadow: none; background: rgba(15,31,58,0.03); }
body.theme-dark .hub-card.new:hover { background: rgba(255,255,255,0.04); }
.hub-card.new .hcn-inner { display: flex; flex-direction: column; align-items: center; gap: 9px; font-weight: 700; font-size: 13.5px; }
.hub-card.new .hcn-plus {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--btn-bg, #DBE5F0); color: var(--btn-fg, #1E2F4A);
  display: flex; align-items: center; justify-content: center;
}
/* Drag-and-drop kortille → lisää PDF:t siihen projektiin */
.hub-card.drag-over {
  outline: 2px solid var(--blue); outline-offset: -2px;
  box-shadow: 0 4px 16px rgba(15,31,58,0.20);
}
#hub-overlay.drag-over { background: linear-gradient(135deg, #f0f7fb 0%, #e8eef3 100%); }
.hub-upload-progress {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--navy, #0E2841); color: #fff;
  padding: 10px 20px; border-radius: var(--radius-xl);
  font-size: 13px; font-weight: 600;
  box-shadow: 0 4px 18px rgba(0,0,0,0.25);
  z-index: 2000;
  display: flex; align-items: center; gap: 10px;
}
#hub-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 80px 20px;
  color: #9ca3af; font-size: 14px;
}

/* Uusi projekti -modaali */
#hub-new-bg {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.45);
  z-index: 1900;
  display: none;
  align-items: center; justify-content: center;
}
#hub-new-bg.show { display: flex; }
#hub-new-modal {
  background: var(--panel); border-radius: 16px;
  padding: 30px 34px 28px;
  width: 100%; max-width: 520px;
  box-shadow: 0 28px 70px rgba(15,31,58,0.22), 0 6px 20px rgba(15,31,58,0.10);
  display: flex; flex-direction: column; gap: 20px;
  /* 2026-07-02 KORJAUS (käyttäjäpalaute "kun vie paljon kuvia hubiin, näkymä liian
     korkea eikä napit näy"): monen PDF:n pudotus kasvatti modaalin ruutua korkeammaksi
     → Luo projekti -napit valuivat näkymättömiin. Nyt modaali ei koskaan ylitä ruutua
     (backstop-scroll) ja tiedostolista scrollaa itse (alla) → napit AINA näkyvissä. */
  max-height: calc(100vh - 40px);
  overflow-y: auto;
}
#hub-new-files { max-height: 28vh; overflow-y: auto; padding-right: 2px; flex: none; }
#hub-new-modal h2 {
  margin: 0; padding-bottom: 18px; border-bottom: 1px solid #E2E8F0;
  font-size: 21px; color: #0F1F3A;
  font-weight: 700; letter-spacing: -0.015em;
  display: flex; align-items: center; gap: 10px;
}
#hub-new-modal h2::before {
  content: '✎'; font-size: 18px; color: #0F1F3A;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--radius-lg);
  background: linear-gradient(180deg, #F1F5F9, #E2E8F0);
}
#hub-new-modal[data-mode="new"] h2::before { content: '✚'; }
#hub-new-modal label {
  display: flex; flex-direction: column; gap: 7px;
  font-size: 12px; color: #475569; font-weight: 600;
  letter-spacing: 0.01em; text-transform: none;
}
#hub-new-modal input {
  padding: 11px 14px; font-size: 14px;
  border: 1px solid #E2E8F0; border-radius: var(--radius-xl);
  font-family: inherit; color: #0F1F3A;
  background: #FAFBFC;
  text-transform: none; letter-spacing: normal; font-weight: 400;
  outline: none; transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
#hub-new-modal input::placeholder { color: #64748B; font-weight: 400; }
#hub-new-modal input:hover { border-color: #CBD5E1; background: var(--panel); }
#hub-new-modal input:focus {
  border-color: #0F1F3A; background: var(--panel);
  box-shadow: 0 0 0 3px rgba(15,31,58,0.10);
}
#hub-new-modal .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
#hub-new-modal .actions {
  display: flex; gap: 10px; justify-content: flex-end;
  margin-top: 10px; padding-top: 18px; border-top: 1px solid #E2E8F0;
}
#hub-new-modal .actions .hub-btn {
  padding: 10px 22px; font-size: 14px; font-weight: 600;
  border: 0; border-radius: var(--radius-xl); cursor: pointer;
  font-family: inherit; letter-spacing: -0.005em;
  transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
}
#hub-new-modal .actions .hub-btn:not(.ghost) {
  background: #0F1F3A; color: #fff;
  box-shadow: 0 2px 6px rgba(15,31,58,0.18);
}
#hub-new-modal .actions .hub-btn:not(.ghost):hover { background: #1E293B; box-shadow: 0 4px 12px rgba(15,31,58,0.25); }
#hub-new-modal .actions .hub-btn:not(.ghost):active { transform: translateY(1px); }
#hub-new-modal .actions .hub-btn.ghost {
  background: #F1F5F9; color: #475569;
}
#hub-new-modal .actions .hub-btn.ghost:hover { background: #E2E8F0; color: #0F1F3A; }

/* 2026-05-22: Hinnasto-modaali CSS poistettu — hinnoittelu siirretty Vektoria_hinnasto.xlsx:ään */

/* ── Projektisivu (HUB v2 taso 2, 2026-07-02): piirustukset thumbnail-kortteina ── */
#hub-detail {
  flex: 1;
  width: 100%; max-width: 1320px; margin: 0 auto;
  padding: 22px 48px 64px;
  display: flex; flex-direction: column; gap: 16px;
}
#hub-detail[hidden] { display: none; }
.hd-topbar { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
/* 2026-07-21 käyttäjäpalaute: "paluu projekteihin hukkuu fonttien sotkuun".
   Juurisyy EI ollut fonttikoko vaan puuttuva affordanssi — nappi oli levossa
   reunaton ja taustaton, ja 13px/700/--text-soft on käytännössä sama kuin
   viereinen .hd-meta (12.5px/--text-soft) → se luki tekstinä, ei kontrollina.
   Korjaus: näkyvä reuna + tausta + --text-väri, koko .hd-open-btn:n tasolle.
   margin-left -11px → 0 on PAKOLLINEN: negatiivinen marginaali oli olemassa
   vain jotta reunaton teksti asettui optisesti #hub-detailin paddingiin;
   näkyvällä reunalla se roikottaisi laatikon sisältöreunan ulkopuolelle.
   Kaikki värit tokeneita → ei erillistä dark-overridea (vrt. .hd-open-btn
   joka kovakoodaa #0F1F3A ja tarvitsi siksi rivin 404 overriden). */
.hd-back {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  font-size: 14px; font-weight: 700; cursor: pointer;
  padding: 10px 16px 10px 13px; border-radius: 10px; margin-left: 0; flex: none;
  font-family: inherit; min-height: 40px; white-space: nowrap;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.hd-back:hover { background: var(--btn-sec-bg, #F1F5F9); border-color: var(--text-muted); color: var(--text); }
.hd-back:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* 2026-07-11 HUB-auditti: min-width oli 0 → flex-kutistus murskasi otsikon ("Folkhälsan…"
   → "F..") ENNEN kuin flex-wrap ehti rivittää toiminnot omalle rivilleen. 180px-lattia →
   otsikko pysyy luettavana ja toimintorivi rivittyy alle kun tila loppuu. */
.hd-titlewrap { min-width: 180px; flex: 1; }
.hd-title {
  font-size: 24px; font-weight: 800; letter-spacing: -0.02em; color: var(--text);
  line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hd-meta { display: flex; gap: 13px; align-items: center; font-size: 12.5px; color: var(--text-soft); margin-top: 4px; flex-wrap: wrap; }
.hd-meta .hd-no { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11.5px; color: var(--text-muted); }
.hd-meta .hd-designer { color: var(--blue); font-weight: 600; }
.hd-actions { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; flex: none; padding-top: 2px; }
/* Kapea ikkuna: toiminnot koko riville otsikon alle (eivät työnnä "Avaa työtilaa" ruudun ulkopuolelle) */
@media (max-width: 900px) {
  .hd-actions { flex: 1 1 100%; justify-content: flex-start; }
  .hd-actions .hd-open-btn { margin-left: auto; }
}
.hd-open-btn {
  background: #0F1F3A; color: #fff; border: 0; border-radius: 11px;
  padding: 11px 22px; font-size: 14px; font-weight: 700; cursor: pointer;
  display: inline-flex; align-items: center; gap: 9px;
  box-shadow: 0 2px 8px rgba(15,31,58,0.22);
  transition: background .15s ease, box-shadow .15s ease;
  font-family: inherit;
}
.hd-open-btn:hover { background: #1E293B; box-shadow: 0 4px 14px rgba(15,31,58,0.30); }
.hd-open-btn[disabled] { opacity: .45; cursor: default; pointer-events: none; }
body.theme-dark .hd-open-btn { background: var(--canvas-accent, #1565C0); }
.hd-sec-btn {
  background: var(--panel); color: var(--btn-sec-fg, #475569);
  border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 15px; font-size: 12.5px; font-weight: 700; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  font-family: inherit;
  transition: border-color .12s, color .12s, background .12s;
}
.hd-sec-btn:hover { border-color: var(--blue); color: var(--blue); }
.hd-sec-btn.danger:hover { border-color: #DC2626; color: #DC2626; background: #FEF2F2; }
.hd-prepbar {
  display: flex; align-items: center; gap: 12px;
  background: var(--panel); border: 1px solid var(--border); border-left: 3px solid var(--blue);
  border-radius: 11px; padding: 11px 16px;
  font-size: 12.5px; font-weight: 700; color: var(--text);
}
.hd-prepbar[hidden] { display: none; }
.hd-prepbar .hp-spin { width: 13px; height: 13px; border: 2px solid var(--border); border-top-color: var(--blue); border-radius: 50%; animation: hp-rot .7s linear infinite; flex: none; }
.hd-prepbar .hp-bar { flex: 1; height: 5px; border-radius: 3px; background: var(--border); overflow: hidden; }
.hd-prepbar .hp-bar i { display: block; height: 100%; width: 0; background: var(--blue); transition: width .3s; }
.hd-prepbar .hp-count { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11.5px; color: var(--text-soft); white-space: nowrap; }
.hd-prepbar.ready { border-left-color: #16A34A; color: #15803D; }
.hd-prepbar.ready .hp-spin { display: none; }
/* 2026-07-25 flow-katselmus BLOCKER B2: epäonnistunut valmistelu on PYSYVÄ tila
   omalla ulospääsyllään. Ennen tästä kertoi vain katoava toast, ja käyttäjälle jäi
   ikuisesti disabloitu "Avaa työtila" + spinneri jonka takana ei tapahtunut mitään. */
.hd-prepbar.failed { border-left-color: #DC2626; color: #B91C1C; justify-content: space-between; }
.hd-prepbar.failed .hd-prep-retry {
  font: inherit; font-size: 12px; font-weight: 700;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--border); border-radius: 8px;
  padding: 5px 12px; cursor: pointer; flex: none;
}
.hd-prepbar.failed .hd-prep-retry:hover { background: var(--btn-bg-hover); }
body.theme-dark .hd-prepbar.failed { color: #FCA5A5; }
.hd-dwg-prep.failed {
  background: rgba(220,38,38,0.14); color: #B91C1C;
  font-weight: 700; font-size: 11.5px; text-align: center;
}
body.theme-dark .hd-dwg-prep.failed { color: #FCA5A5; background: rgba(220,38,38,0.22); }
.hd-dwg.prep-failed { outline: 1px solid rgba(220,38,38,0.45); }
/* 2026-07-25 flow-katselmus B9: latausvirheen ulospääsy (Hub-ruudukko + projektisivu).
   Ennen ruudulle jäi pelkkä raaka virheteksti eikä mitään keinoa yrittää uudelleen. */
.hd-retry {
  margin-top: 10px; font: 600 12.5px/1 inherit;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--border); border-radius: 9px;
  padding: 8px 14px; cursor: pointer;
}
.hd-retry:hover { background: var(--btn-bg-hover); }
/* 2026-07-18 tuonnin edistymis-UX ("tuntuu että ei etene, onko homma hengissä"):
   (1) parhaillaan valmisteltavan tiedoston nimi näkyviin palkkiin (hp-cur);
   (2) käynnissä olevaan palkkiin elävä shimmer-juova → näyttää elossa myös kun
   yksi iso CAD-sivu kestää kymmeniä sekunteja eikä N/M-luku liiku.
   prefers-reduced-motion-yleissääntö (01-base-12.css) pysäyttää animaation. */
.hd-prepbar .hp-cur {
  font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11px;
  font-weight: 600; color: var(--blue);
  background: var(--btn-sec-bg, #F1F5F9); border: 1px solid var(--border);
  border-radius: 99px; padding: 2px 10px;
  max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  flex: none;
}
body.theme-dark .hd-prepbar .hp-cur { background: rgba(255,255,255,0.06); }
.hd-prepbar .hp-bar { position: relative; }
.hd-prepbar .hp-bar.running::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,0.55) 50%, transparent 70%);
  transform: translateX(-100%); animation: hc-shimmer 1.3s ease-in-out infinite;
}
body.theme-dark .hd-prepbar .hp-bar.running::after {
  background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,0.18) 50%, transparent 70%);
}
/* Parhaillaan valmisteltavan piirustuksen kortti: hienovarainen pulssi-hehku */
@keyframes prep-now-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(21,101,192,0); }
  50%      { box-shadow: 0 0 0 4px rgba(21,101,192,0.22); }
}
.hd-dwg.prep-now { outline: 2px solid var(--blue); outline-offset: -2px; animation: prep-now-glow 1.6s ease-in-out infinite; }
.hd-drop {
  border: 2px dashed var(--border); border-radius: 13px;
  background: var(--panel);
  padding: 15px 18px;
  display: flex; align-items: center; justify-content: center; gap: 11px;
  color: var(--text-soft); font-size: 13px; cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.hd-drop b { color: var(--text); }
.hd-drop svg { flex: none; opacity: .8; }
.hd-drop:hover, .hd-drop.over { border-color: var(--blue); background: rgba(15,31,58,0.04); color: var(--text); }
body.theme-dark .hd-drop:hover, body.theme-dark .hd-drop.over { background: rgba(255,255,255,0.05); }
.hd-sys { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; overflow: hidden; }
.hd-sys-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--panel-soft, #FAFAFB);
}
body.theme-dark .hd-sys-head { background: rgba(255,255,255,0.03); }
.hd-sys-name { font-size: 13.5px; font-weight: 800; color: var(--text); letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hd-sys-meta { font-size: 11.5px; font-weight: 600; color: var(--text-muted); font-family: 'JetBrains Mono', ui-monospace, monospace; white-space: nowrap; }
.hd-sys-head .spacer { flex: 1; }
.hd-sys-act {
  background: none; border: 1px solid transparent; border-radius: 7px;
  color: var(--text-muted); cursor: pointer; padding: 4px 10px;
  font-size: 11.5px; font-weight: 700; display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit; white-space: nowrap;
}
.hd-sys-act:hover { background: var(--btn-sec-bg, #F1F5F9); color: var(--text); }
.hd-sys-act svg { stroke: currentColor; }
.hd-drawings {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px; padding: 16px 18px;
}
.hd-dwg {
  border: 1px solid var(--border); border-radius: 11px; overflow: hidden;
  cursor: pointer; background: var(--panel); position: relative;
  transition: box-shadow .15s, transform .12s, border-color .15s;
}
.hd-dwg:hover { box-shadow: 0 8px 20px rgba(15,31,58,0.13); transform: translateY(-2px); border-color: #C9D4E3; }
body.theme-dark .hd-dwg:hover { border-color: rgba(255,255,255,0.22); }
.hd-dwg:focus-visible { outline: 2px solid var(--canvas-accent, #1565C0); outline-offset: 2px; }
.hd-dwg-thumb {
  height: 118px; position: relative; overflow: hidden;
  background: linear-gradient(180deg, #F4F6FA, #ECEFF5);
  border-bottom: 1px solid var(--border);
}
body.theme-dark .hd-dwg-thumb { background: rgba(255,255,255,0.04); }
.hd-dwg-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; background: #fff; }
.hd-dwg-thumb .ph { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--text-faint, #9A9AA0); }
/* 2026-07-02 HUB-flow (#13): valmistelu-spinner piirustuskortin kuva-alueella (Countfire)
   + thumbin fade-in kun valmistuu. .preparing-kortti ei hover-nouse (ei vielä avattavissa). */
.hd-dwg-prep { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px; font-size: 11px; font-weight: 700; color: var(--blue); background: linear-gradient(180deg, #F4F6FA, #ECEFF5); }
body.theme-dark .hd-dwg-prep { background: rgba(255,255,255,0.05); color: var(--text-soft); }
.hd-dwg-prep .hp-spin { width: 18px; height: 18px; border: 2.5px solid var(--border); border-top-color: var(--blue); border-radius: 50%; animation: hp-rot .7s linear infinite; }
.hd-dwg.preparing { cursor: default; }
.hd-dwg.preparing:hover { transform: none; box-shadow: none; border-color: var(--border); }
/* 2026-07-05 (B4): piirustuskortin poistonappi (✕) — poistaa piirustuksen projektin
   listalta hubista (tiedosto säilyy levyllä). Näkyy hoverilla, sama danger-tyyli
   kuin työtilan .file-del. Absoluuttinen kulmassa, oma z-index kortin onclickin yli. */
.hd-dwg-del {
  position: absolute; top: 6px; right: 6px; z-index: 3;
  width: 24px; height: 24px; padding: 0; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 7px; cursor: pointer;
  font-size: 15px; font-weight: 700;
  color: #fff; background: rgba(15,31,58,0.55);
  opacity: 0; transition: opacity .12s, background .12s;
}
.hd-dwg:hover .hd-dwg-del, .hd-dwg:focus-within .hd-dwg-del { opacity: 1; }
.hd-dwg-del:hover { background: var(--danger, #DC2626); }
.hd-dwg-del:focus-visible { opacity: 1; outline: 2px solid #fff; outline-offset: 1px; }
.hd-dwg-thumb img.hd-thumb-in { animation: hd-thumb-fade .35s ease; }
@keyframes hd-thumb-fade { from { opacity: 0; } to { opacity: 1; } }
.hd-dwg-name {
  font-size: 11px; font-family: 'JetBrains Mono', ui-monospace, monospace; color: var(--text);
  padding: 8px 10px 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hd-dwg-foot { display: flex; align-items: center; justify-content: space-between; padding: 0 10px 8px; min-height: 22px; }
.hd-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 700; border-radius: 99px; padding: 2px 8px; white-space: nowrap; }
.hd-badge.ready { color: #15803D; background: #F0FDF4; border: 1px solid #BBF7D0; }
.hd-badge.prep { color: #1D4ED8; background: #EFF6FF; border: 1px solid #BFDBFE; }
.hd-badge.prep .hp-spin { width: 9px; height: 9px; border: 2px solid rgba(29,78,216,0.25); border-top-color: #1D4ED8; border-radius: 50%; animation: hp-rot .7s linear infinite; }
.hd-badge.err { color: #B91C1C; background: #FEF2F2; border: 1px solid #FECACA; }
body.theme-dark .hd-badge.ready { color: #4ADE80; background: rgba(22,163,74,0.12); border-color: rgba(22,163,74,0.35); }
body.theme-dark .hd-badge.prep { color: #93C5FD; background: rgba(37,99,235,0.14); border-color: rgba(59,130,246,0.40); }
.hd-addsys {
  align-self: flex-start;
  background: var(--btn-bg, #DBE5F0); color: var(--btn-fg, #1E2F4A); border: 0;
  font-size: 12.5px; font-weight: 700; border-radius: 9px; padding: 9px 16px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px; font-family: inherit;
}
.hd-addsys:hover { background: var(--btn-bg-hover, #C2D2E5); }
.hd-empty { text-align: center; padding: 46px 16px; color: var(--text-muted); font-size: 13.5px; line-height: 1.8; }
.hd-empty b { color: var(--text); }
/* Valmistelun elonmerkki (2026-07-21): tikittävä sekuntilukema on se todiste
   jota spinneri ei anna. Hidas = rauhoittava sävy, ei-vastaa = varoitus. */
.hd-prepbar .hp-live {
  font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text-soft); white-space: nowrap;
}
.hd-prepbar.slow .hp-live { color: #B45309; }
.hd-prepbar.stalled { border-color: #FECACA; background: #FEF2F2; }
.hd-prepbar.stalled .hp-live { color: #B91C1C; white-space: normal; }
.hd-prepbar.stalled .hp-spin { animation-play-state: paused; opacity: .4; }
body.theme-dark .hd-prepbar.slow .hp-live { color: #FBBF24; }
body.theme-dark .hd-prepbar.stalled { border-color: rgba(185,28,28,0.45); background: rgba(185,28,28,0.12); }
body.theme-dark .hd-prepbar.stalled .hp-live { color: #FCA5A5; }
/* Tuonnin aikana tyhjä-tila pois: jono itse kertoo mitä tapahtuu, ja
   "Ei vielä piirustuksia" sen vieressä olisi suoraan harhaanjohtava. */
#hub-detail.hd-importing .hd-empty { display: none; }
/* Tuontijono (2026-07-20): näkyvä palaute heti tiedostovalinnasta, ei jäistä ruutua.
   Tilat: queued -> sending -> ok | duplicate | error. Mitään ei merkitä valmiiksi
   ennen palvelimen kuittausta. */
.hd-upq { border: 1px solid var(--border); border-radius: 11px; background: var(--panel); overflow: hidden; }
.hd-upq-head {
  display: flex; align-items: center; gap: 9px; padding: 10px 14px;
  font-size: 12.5px; font-weight: 700; color: var(--text);
  border-bottom: 1px solid var(--border);
}
.hd-upq-head .hp-spin { width: 13px; height: 13px; border: 2px solid var(--border); border-top-color: var(--blue); border-radius: 50%; animation: hp-rot .7s linear infinite; flex: none; }
.hd-upq-list { display: flex; flex-direction: column; }
.hd-upq-item { display: flex; align-items: center; gap: 9px; padding: 7px 14px; font-size: 12px; }
.hd-upq-item + .hd-upq-item { border-top: 1px solid var(--border); }
.hd-upq-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-muted); flex: none; }
.hd-upq-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.hd-upq-state { flex: none; font-size: 11px; font-weight: 700; color: var(--text-soft); }
.hd-upq-item.is-sending .hd-upq-dot { background: var(--blue); animation: hp-pulse 1s ease-in-out infinite; }
.hd-upq-item.is-sending .hd-upq-state { color: #1D4ED8; }
.hd-upq-item.is-ok .hd-upq-dot { background: #15803D; }
.hd-upq-item.is-ok .hd-upq-state { color: #15803D; }
.hd-upq-item.is-duplicate .hd-upq-dot { background: #B45309; }
.hd-upq-item.is-duplicate .hd-upq-state { color: #B45309; }
.hd-upq-item.is-error .hd-upq-dot { background: #B91C1C; }
.hd-upq-item.is-error .hd-upq-state { color: #B91C1C; }
@keyframes hp-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
body.theme-dark .hd-upq-item.is-ok .hd-upq-state { color: #4ADE80; }
body.theme-dark .hd-upq-item.is-ok .hd-upq-dot { background: #4ADE80; }
body.theme-dark .hd-upq-item.is-sending .hd-upq-state { color: #93C5FD; }
body.theme-dark .hd-upq-item.is-duplicate .hd-upq-state { color: #FBBF24; }
body.theme-dark .hd-upq-item.is-duplicate .hd-upq-dot { background: #FBBF24; }
body.theme-dark .hd-upq-item.is-error .hd-upq-state { color: #FCA5A5; }
body.theme-dark .hd-upq-item.is-error .hd-upq-dot { background: #FCA5A5; }
@media (prefers-reduced-motion: reduce) {
  .hd-upq-item.is-sending .hd-upq-dot { animation: none; }
}
@media (max-width: 900px) {
  #hub-header { padding: 16px 20px; }
  #hub-grid { padding: 18px 20px 40px; }
  #hub-detail { padding: 16px 20px 48px; }
}

  /* 📊 Yhteenveto-matriisi — sticky header + ensimmäinen sarake */
  #quantities-table-wrap table { border-collapse: separate; border-spacing: 0; font-size: 12px; width: max-content; min-width: 100%; }
  #quantities-table-wrap th, #quantities-table-wrap td {
    border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
    padding: 5px 9px; text-align: center; white-space: nowrap; background: var(--panel);
  }
  /* Sticky ylärivi (kuva-otsikot) */
  #quantities-table-wrap thead th {
    position: sticky; top: 0; z-index: 3; background: var(--navy); color: #fff;
    font-weight: 600; font-size: 11px; vertical-align: bottom; max-width: 150px;
    white-space: normal; line-height: 1.25;
  }
  /* Sticky vasen sarake (tuotenimet) */
  #quantities-table-wrap th.qm-rowhead, #quantities-table-wrap td.qm-rowhead {
    position: sticky; left: 0; z-index: 2; text-align: left; font-weight: 600;
    background: #F8FAFC; min-width: 200px; max-width: 320px; white-space: normal;
  }
  #quantities-table-wrap thead th.qm-corner { z-index: 4; left: 0; background: var(--navy); }
  /* Määrä-solut */
  #quantities-table-wrap td.qm-cell { font-family: 'JetBrains Mono', ui-monospace, monospace; color: var(--text); }
  #quantities-table-wrap td.qm-cell.qm-zero { color: #CBD5E1; }
  #quantities-table-wrap td.qm-cell.qm-has { font-weight: 600; }
  /* Yhteensä-sarake + rivi */
  #quantities-table-wrap td.qm-total, #quantities-table-wrap th.qm-total {
    background: var(--bark-light); font-weight: 700; font-family: 'JetBrains Mono', monospace;
    position: sticky; right: 0; z-index: 2;
  }
  #quantities-table-wrap thead th.qm-total { z-index: 3; background: var(--navy); color: #fff; right: 0; }
  #quantities-table-wrap tr.qm-totalrow td {
    background: var(--bark-light); font-weight: 700; font-family: 'JetBrains Mono', monospace;
    position: sticky; bottom: 0; z-index: 1;
  }
  #quantities-table-wrap tr.qm-totalrow td.qm-rowhead { z-index: 3; }
  #quantities-table-wrap tr.qm-totalrow td.qm-grand { background: var(--navy); color: #fff; z-index: 4; right:0; }
  #quantities-table-wrap tbody tr:hover td:not(.qm-rowhead):not(.qm-total) { background: #EFF6FF; }
  #quantities-table-wrap .qm-swatch { display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:6px;vertical-align:-1px; }
  #quantities-table-wrap .qm-own { color: #C2680A; }

  #est-settings-bg .set-sec { border:1px solid var(--border); border-radius:11px; margin-bottom:14px; overflow:hidden; background:var(--panel); }
  #est-settings-bg .set-sec:last-child { margin-bottom:0; }
  #est-settings-bg .set-sec-h { font-size:11px; font-weight:700; letter-spacing:0.4px; text-transform:uppercase; color:var(--text-muted); padding:10px 14px; background:var(--bg); border-bottom:1px solid var(--border); display:flex; align-items:center; gap:8px; }
  #est-settings-bg .set-sec-h-meta { font-weight:600; letter-spacing:0; text-transform:none; color:var(--text-muted); font-size:10.5px; }
  #est-settings-bg .set-sec-b { padding:13px 14px; }
  #est-settings-bg .set-sec-note { font-size:12px; color:#64748B; line-height:1.55; margin:8px 0 0; }
  /* 2026-07-27: käyttäjäasetusrivi (Ulkoasu → Teema). Nimiö vasemmalle, kontrolli
     oikealle — sama luenta kuin Näkymä ▾ -valikon vm-row jossa teema ennen asui. */
  #est-settings-bg .set-pref-row { display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
  #est-settings-bg .set-pref-label { font-size:13px; font-weight:600; color:var(--text); flex:1 1 auto; }
  #est-settings-bg .set-btn-primary { display:inline-flex; align-items:center; gap:7px; background:#DBE5F0; color:#1E2F4A; border:none; border-radius:9px; padding:9px 15px; font-weight:600; font-size:13px; cursor:pointer; }
  #est-settings-bg .set-btn-primary:hover { background:#C2D2E5; }
  #est-settings-bg .set-btn-primary svg { width:14px; height:14px; }
  #est-settings-bg .set-reg-status { font-size:13px; font-weight:600; padding:9px 12px; border-radius:9px; background:#F1F5F9; color:#475569; }
  #est-settings-bg .set-reg-status.on { background:#ECFDF3; color:#067647; }
  #est-settings-bg .set-steps { list-style:none; margin:12px 0 2px; padding:0; }
  #est-settings-bg .set-steps li { display:flex; gap:11px; padding:12px 0; border-top:1px solid #EEF2F6; }
  #est-settings-bg .set-steps li:first-child { border-top:none; padding-top:4px; }
  #est-settings-bg .set-step-n { flex:0 0 22px; height:22px; border-radius:50%; background:#0F1F3A; color:#fff; font-size:12px; font-weight:700; display:flex; align-items:center; justify-content:center; margin-top:1px; }
  #est-settings-bg .set-step-b { flex:1; min-width:0; }
  #est-settings-bg .set-step-t { font-size:13.5px; font-weight:700; color:#0F1F3A; margin:1px 0 8px; }
  #est-settings-bg .set-step-d { font-size:12px; color:#64748B; line-height:1.5; }
  #est-settings-bg .set-row { display:flex; gap:8px; }
  #est-settings-bg .set-row button { flex:1; padding:10px; border:none; border-radius:9px; font-weight:600; cursor:pointer; font-size:13px; background:#F1F5F9; color:#475569; }
  #est-settings-bg .set-row button.primary { background:#DBE5F0; color:#1E2F4A; }
  #est-settings-bg .set-row button:hover { filter:brightness(0.97); }
  #est-settings-bg .set-reg-msg { margin-top:10px; font-size:12.5px; display:none; }
  #est-settings-bg .set-reg-msg.err { display:block; color:#B42318; }
  #est-settings-bg .set-reg-msg.ok { display:block; color:#067647; }
  #est-settings-bg .set-reg-foot { margin-top:12px; display:flex; justify-content:flex-start; }
  #est-settings-bg .set-reg-foot button.danger { background:#FEF3F2; color:#B42318; border:none; border-radius:9px; padding:8px 14px; cursor:pointer; font-weight:600; font-size:12.5px; }

        #settings-hinnasto-sec .est-lh-globals{display:flex;flex-wrap:wrap;gap:14px;margin-bottom:10px;align-items:flex-end}
        #settings-hinnasto-sec .est-lh-fld{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--text-muted)}
        #settings-hinnasto-sec .est-lh-fld input{width:100px;padding:5px 7px;border:1px solid var(--border);border-radius:7px;background:var(--panel);color:var(--text);font-size:12px}
        #settings-hinnasto-sec .est-lh-mt{margin:8px 0;padding:9px 11px;border:1px solid var(--border);border-radius:9px;background:var(--bg)}
        #settings-hinnasto-sec .est-lh-mt h4{margin:0 0 6px;font-size:11px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px}
        #settings-hinnasto-sec .est-lh-mt-row{display:flex;gap:7px;margin-bottom:5px;align-items:center}
        #settings-hinnasto-sec .est-lh-mt-row input{padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font-size:12px}
        #settings-hinnasto-sec .est-lh-mini{font-size:10px;padding:2px 8px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text-muted);cursor:pointer}
        #settings-hinnasto-sec #est-lh-table-wrap{max-height:460px;overflow:auto;border:1px solid var(--border);border-radius:9px;margin-top:4px}
        #settings-hinnasto-sec table.est-lh-table{width:100%;min-width:700px;table-layout:fixed;border-collapse:collapse;font-size:12px}
        #settings-hinnasto-sec .est-lh-table th{text-align:left;font-size:10px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.03em;padding:6px 8px;border-bottom:1px solid var(--border);position:sticky;top:0;background:var(--panel);z-index:1}
        #settings-hinnasto-sec .est-lh-table td{padding:3px 8px;border-bottom:1px solid var(--border);vertical-align:top}
        #settings-hinnasto-sec .est-lh-table th:nth-child(1),#settings-hinnasto-sec .est-lh-table td:nth-child(1){width:185px}
        #settings-hinnasto-sec .est-lh-table th:nth-child(3),#settings-hinnasto-sec .est-lh-table td:nth-child(3),#settings-hinnasto-sec .est-lh-table th:nth-child(4),#settings-hinnasto-sec .est-lh-table td:nth-child(4){width:94px}
        #settings-hinnasto-sec .est-lh-table th:nth-child(5),#settings-hinnasto-sec .est-lh-table td:nth-child(5){width:108px}
        #settings-hinnasto-sec .est-lh-table th:nth-child(6),#settings-hinnasto-sec .est-lh-table td:nth-child(6){width:160px}
        #settings-hinnasto-sec .est-lh-table td input{width:100%;padding:5px 7px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font-size:12px}
        #settings-hinnasto-sec .est-lh-table td input:focus{border-color:var(--canvas-accent,#1565C0);outline:none}
        #settings-hinnasto-sec .est-lh-table td:nth-child(1) code{font-size:11px;color:var(--text);white-space:normal;word-break:break-word;display:inline-block;line-height:1.3}
        #settings-hinnasto-sec .est-lh-name{display:block;color:var(--text-muted);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
      
  /* 2026-06-30: modaalit venytettäviksi (käyttäjäpyyntö "venytettävät ja skaalautuvat").
     Vedä oikeasta alakulmasta. resize toimii overflow!=visible -elementeillä; modaaleilla
     on overflow:hidden inline → ok. min-koko ettei mene olemattomiin; max-koko inline-tyylien
     (max-width/max-height) mukaan. */
  #estimate-modal, #library-modal, #gallery-modal, #quantities-modal, #models-modal,
  #stamp-picker-modal, #copy-sys-modal, #batch-summary-modal, #feature-admin,
  #est-settings-bg > div {
    resize: both;
    min-width: 360px;
    min-height: 240px;
    position: relative;
  }
  /* selvempi tarttumakahva oikeaan alakulmaan (natiivi resize-grabber on vaisu) */
  #estimate-modal::after, #library-modal::after, #gallery-modal::after, #quantities-modal::after,
  #models-modal::after, #stamp-picker-modal::after, #copy-sys-modal::after, #batch-summary-modal::after,
  #feature-admin::after, #est-settings-bg > div::after {
    content: ""; position: absolute; right: 3px; bottom: 3px; width: 12px; height: 12px;
    border-right: 2px solid var(--text-muted); border-bottom: 2px solid var(--text-muted);
    opacity: 0.45; pointer-events: none; border-bottom-right-radius: 4px;
  }
  
  /* 🧮 Estimaattori-modaali — kompakti (E7-päivitys 2026-05-19) */
  /* ── 2026-06-12 ESTIMAATTORI V2: YKSI NÄKYMÄ (spec Osa F) ──────────────────
     Vasen palsta = rivit osioina, oikea = elävä yhteenveto (sticky). Tilarivi
     ylhäällä kertoo puutteet; est-issues-only suodattaa vain puutteelliset. */
  /* 2026-06-30: vedettävä JAKAJA (sauma) vasemman tuoteosuuden ja oikean tarjouslaskennan
     välissä — vedä saumasta oikealle/vasemmalle. Leveyttä ohjaa --est-right-w (säilyy
     localStorageen). Korvasi vanhan oikean kulman resize-kahvan. */
  .est-v2-grid { display: grid; grid-template-columns: minmax(280px, 1fr) 12px var(--est-right-w, 472px);
    gap: 0; align-items: start; }
  @media (max-width: 1240px) { .est-v2-grid { grid-template-columns: 1fr; } .est-splitter { display: none; } }
  .est-splitter { align-self: stretch; position: sticky; top: -10px; cursor: col-resize;
    height: calc(100vh - 215px); margin: 0 5px; width: 2px; border-radius: 3px;
    background: var(--border); transition: background .12s, box-shadow .12s; touch-action: none; }
  .est-splitter::before { content: ""; position: absolute; left: -6px; right: -6px; top: 0; bottom: 0; }
  .est-splitter:hover, .est-splitter.est-splitter-drag { background: var(--navy, #334155);
    box-shadow: 0 0 0 1px var(--navy, #334155); }
  .est-v2-grid .est-right { position: sticky; top: -10px; max-height: calc(100vh - 215px); overflow: auto;
    width: auto; min-width: 0;
    background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; }
  .est-sec { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; margin-bottom: 12px; overflow: hidden; }
  .est-sec-head { padding: 9px 12px; font-weight: 700; font-size: 12.5px; cursor: pointer; user-select: none;
    background: var(--panel-soft); border-bottom: 1px solid var(--border-soft); display: flex; align-items: center; gap: 7px; }
  .est-sec-head:hover { background: #EEF3FB; }
  .est-sec-caret { font-family: monospace; color: var(--text-muted); }
  .est-sec-body { padding: 8px 12px 12px; }
  .est-sec.est-collapsed .est-sec-body { display: none; }
  .est-sec.est-collapsed .est-sec-head { border-bottom: 0; }
  .est-status-strip { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; }
  .est-chip { border: 1px solid var(--border); border-radius: 99px; padding: 4px 12px; font-size: 11.5px;
    font-weight: 700; background: var(--panel); cursor: default; font-family: inherit; }
  button.est-chip { cursor: pointer; }
  button.est-chip:hover { filter: brightness(0.97); }
  .est-chip-ok { color: #166534; border-color: #BBE3C8; background: #F0FAF3; }
  .est-chip-warn { color: #92400E; border-color: #F5D08C; background: #FFF8EB; }
  .est-chip-err { color: #B3261E; border-color: #F3B6B2; background: #FDF0EF; }
  .est-chip-hint { font-size: 11px; color: var(--text-muted); }
  .est-issues-only tr.est-row-ok { display: none; }
  .est-input.est-overridden { background: #EAF2FE; border-color: #9FC2F2; font-weight: 700; }
  /* 2026-05-29: välilehdet (5 kululajia + Yhteenveto) — yksi kululaji kerrallaan */
  #estimate-tabs {
    position: sticky;
    top: -10px; /* kumoaa estimate-bodyn paddingin yläosan */
    z-index: 5;
    display: flex;
    gap: 4px;
    padding: 6px 0 8px 0;
    margin: -10px 0 10px 0;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    flex-wrap: wrap;
  }
  #estimate-tabs .est-tab {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 7px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--panel);
    color: var(--text-muted);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
  }
  #estimate-tabs .est-tab:hover { background: #F1F5F9; color: var(--text); }
  #estimate-tabs .est-tab.active {
    background: var(--navy);
    color: #fff;
    border-color: var(--text);
  }
  #estimate-tabs .est-tab .est-tab-badge {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    font-weight: 700;
    padding: 0 5px;
    border-radius: var(--radius-lg);
    background: rgba(15,31,58,0.10);
    color: inherit;
  }
  #estimate-tabs .est-tab.active .est-tab-badge { background: rgba(255,255,255,0.22); }
  .est-tab-panel { display: none; }
  .est-tab-panel.active { display: block; }
  /* Alapalkin kojelauta-strip (TARJOUS aina näkyvissä) */
  #estimate-footer { align-items: center; gap: 12px; }
  #estimate-totals .est-strip-tarjous {
    font-size: 14px;
    color: var(--text);
    white-space: nowrap;
  }
  #estimate-totals .est-strip-tarjous b { font-size: 17px; font-family: 'JetBrains Mono', monospace; color: #0F1F3A; }
  #estimate-totals .est-strip-tarjous small { color: var(--text-muted); font-size: 11px; }
  #estimate-totals .est-strip-optio {
    font-size: 12px;
    color: #92400e;
    background: #fffaf0;
    border: 1px solid #fde68a;
    padding: 2px 8px;
    border-radius: var(--radius-md);
    white-space: nowrap;
  }
  #estimate-totals .est-strip-warn {
    font-size: 12px;
    color: #92400e;
    background: #fef3c7;
    border: 1px solid #f59e0b;
    padding: 3px 10px;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-weight: 600;
  }
  #estimate-totals .est-strip-warn:hover { background: #fde68a; }
  #estimate-content .est-section {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    margin-bottom: 12px;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(15,31,58,0.04);
  }
  #estimate-content .est-section-head {
    background: var(--navy);
    padding: 7px 14px;
    border-bottom: 1px solid var(--border);
    font-weight: 700;
    font-size: 12px;
    color: #fff;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  #estimate-content .est-section-meta {
    margin-left: auto;
    color: #fff;
    opacity: 0.75;
    font-weight: 500;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
  }
  /* E7c: Tuotteet-osion sisäinen väliotsikko (Rekisteristä / Manuaaliset) */
  #estimate-content .est-subsection-head {
    background: #fafbfc;
    padding: 4px 14px;
    border-bottom: 1px solid var(--border);
    border-top: 1px solid var(--border);
    font-size: 10.5px;
    color: var(--text-muted);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
  }
  #estimate-content .est-subsection-head:first-of-type {
    border-top: 0;
  }
  #estimate-content .est-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 11.5px;
  }
  #estimate-content .est-table th,
  #estimate-content .est-table td {
    padding: 4px 10px;
    text-align: left;
    border-bottom: 1px solid var(--border);
  }
  #estimate-content .est-table th {
    background: #fafbfc;
    color: var(--text-muted);
    font-weight: 600;
    font-size: 9.5px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    padding: 5px 10px;
  }
  #estimate-content .est-table tbody tr:last-child td { border-bottom: 0; }
  #estimate-content .est-table tbody tr:hover { background: #fbfcfe; }
  #estimate-content .est-table .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-family: 'JetBrains Mono', monospace;
  }
  #estimate-content .est-status-dot {
    display: inline-block;
    width: 9px; height: 9px; border-radius: 50%;
    vertical-align: middle;
  }
  #estimate-content .est-status-dot.ok { background: #4caf50; }
  #estimate-content .est-status-dot.no_price { background: #ffb84a; }
  #estimate-content .est-status-dot.no_rekisteri { background: #d34f3a; }
  /* LOHKO 1.3 (2026-07-10): remapin kohde puuttuu — sama vakavuus kuin no_rekisteri */
  #estimate-content .est-status-dot.remap_missing { background: #d34f3a; }
  #estimate-content .est-warnings {
    background: #fff7e6;
    border: 1px solid #ffd591;
    padding: 7px 12px;
    border-radius: var(--radius-sm);
    margin-bottom: 10px;
    font-size: 11px;
    color: var(--text);
  }
  /* 2026-06-27: dark-teema — Huomioita-laatikko ei saa jäädä kerma-taustalle (themed-teksti → näkymätön) */
  body.theme-dark #estimate-content .est-warnings { background: rgba(234,179,8,0.12); border-color: rgba(234,179,8,0.4); }
  #estimate-content .est-warnings ul { margin: 3px 0 0; padding-left: 18px; }
  #estimate-content .est-empty {
    padding: 8px 14px;
    color: var(--text-muted);
    font-size: 11px;
    font-style: italic;
  }
  #estimate-content .est-row-tyo {
    display: flex; align-items: center; gap: 12px;
    padding: 5px 14px;
    border-bottom: 1px solid var(--border);
    font-size: 11.5px;
  }
  #estimate-content .est-row-tyo:last-child { border-bottom: 0; }
  #estimate-content .est-row-tyo .est-tyo-name { flex: 0 0 110px; font-weight: 600; font-size: 11.5px; }
  #estimate-content .est-row-tyo .est-tyo-detail {
    flex: 1; color: var(--text-muted); font-size: 10.5px;
    font-family: 'JetBrains Mono', monospace;
  }
  #estimate-content .est-row-tyo .est-tyo-eur {
    font-variant-numeric: tabular-nums;
    font-family: 'JetBrains Mono', monospace;
    font-weight: 700; min-width: 80px; text-align: right;
    font-size: 12px;
  }
  /* E7-jatko v3 2026-05-19: footer-yhteenveto taulukko-tyylinä */
  #estimate-totals {
    width: 100%;
    display: block;
  }
  .est-summary-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
  }
  .est-summary-table th {
    padding: 3px 10px;
    text-align: right;
    font-size: 9.5px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
    font-weight: 700;
    border-bottom: 1px solid var(--border);
  }
  .est-summary-table th:first-child {
    text-align: left;
  }
  .est-summary-table td {
    padding: 4px 10px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
  }
  .est-summary-table td:first-child {
    font-weight: 600;
    color: var(--text);
  }
  .est-summary-table td.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-family: 'JetBrains Mono', monospace;
  }
  .est-summary-table td.est-dim {
    color: var(--text-muted);
    opacity: 0.7;
  }
  .est-summary-table .est-input {
    width: 50px !important;
    padding: 1px 5px !important;
    font-size: 11px !important;
    text-align: right;
  }
  /* Tarjous-yhteenveto (korostettu rivi) */
  .est-summary-total td {
    background: var(--navy);
    color: #fff;
    font-weight: 800;
    font-size: 13px;
    padding: 6px 10px;
    border-bottom: 0;
  }
  .est-summary-total td:first-child {
    color: #fff;
    letter-spacing: 0.5px;
  }
  .est-summary-total td:last-child {
    font-size: 15px;
  }
  /* Optiot — keltainen tausta, viimeinen rivi */
  .est-summary-option-row td {
    background: #fff7e6;
    color: #7a5500;
    font-style: italic;
    font-size: 11px;
    border-bottom: 0;
  }
  .est-summary-option-row td:first-child {
    color: #7a5500;
  }
  /* Per-rivin optio-checkbox Lisäkulut-taulukossa */
  #estimate-content .est-optio-cell {
    text-align: center;
    color: var(--text-muted);
    font-size: 10px;
  }
  #estimate-content .est-optio-cell input { transform: scale(0.9); }
  #estimate-content .est-optio-row { background: #fffaf0; }
  /* E4 — muokattavat kentät (kompakti) */
  #estimate-content .est-input {
    padding: 2px 5px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 11px;
    font-family: inherit;
    background: var(--panel);
    color: var(--text);
    box-sizing: border-box;
  }
  #estimate-content .est-input:focus {
    outline: none;
    border-color: var(--btn-bg);
    box-shadow: 0 0 0 2px rgba(127,168,206,0.25);
  }
  #estimate-content .est-input[type="number"] {
    font-variant-numeric: tabular-nums;
    font-family: 'JetBrains Mono', monospace;
  }
  /* Piilota number-input:n nuolet (selkeämpi ulkoasu) */
  #estimate-content .est-input[type="number"]::-webkit-inner-spin-button,
  #estimate-content .est-input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none; margin: 0;
  }
  #estimate-content .est-input[type="number"] { -moz-appearance: textfield; }
  #estimate-content .est-add-btn {
    margin-left: auto;
    background: rgba(255,255,255,0.15);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.5);
    border-radius: 5px;
    padding: 2px 9px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
  }
  #estimate-content .est-add-btn:hover { background: var(--panel); color: var(--text); border-color: #fff; }
  /* 2026-05-30: .est-add-btn on tyylitelty tummalle section-headille (valkoinen teksti).
     Vaaleilla taustoilla (esim. Aliurakat-toolbar) se oli näkymätön ennen hoveria → anna
     näkyvä laventeli-sininen tyyli. */
  #estimate-content .est-ext-toolbar .est-add-btn {
    margin-left: 0;
    background: var(--btn-bg);
    color: var(--btn-fg);
    border-color: var(--btn-bg);
  }
  #estimate-content .est-ext-toolbar .est-add-btn:hover {
    background: var(--btn-bg-hover);
    color: var(--btn-fg);
    border-color: var(--btn-bg-hover);
  }
  #estimate-content .est-del-btn {
    background: transparent;
    color: var(--text-muted);
    border: 0;
    border-radius: var(--radius-sm);
    padding: 1px 8px;
    font-size: 15px;
    cursor: pointer;
    line-height: 1;
  }
  #estimate-content .est-del-btn:hover {
    color: #d34f3a;
    background: rgba(211, 79, 58, 0.08);
  }
  /* Override-input footerissa */
  #estimate-totals .est-tot-card .est-input {
    padding: 2px 4px;
    font-size: 11px;
    height: auto;
  }
  /* 2026-05-29 Aliurakat-osio — koko sähköurakkalaskennan tuki */
  #estimate-content .est-ext-toolbar {
    padding: 8px 12px;
    background: #fafbfc;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    font-size: 11.5px;
  }
  #estimate-content .est-ext-or {
    color: var(--text-muted);
    font-size: 11px;
  }
  #estimate-content .est-ext-preset-select {
    padding: 4px 8px;
    font-size: 11.5px;
    height: auto;
    min-width: 230px;
  }
  #estimate-content .est-ext-hint {
    margin-left: auto;
    color: var(--text-muted);
    font-size: 10.5px;
    font-style: italic;
    flex: 1;
    text-align: right;
    min-width: 200px;
  }
  #estimate-content .est-ext-empty {
    padding: 22px 14px;
    text-align: center;
    color: var(--text-muted);
    font-size: 12px;
    font-style: italic;
  }
  #estimate-content .est-ext-rows {
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  #estimate-content .est-ext-row {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 10px 12px;
    position: relative;
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
  }
  #estimate-content .est-ext-row.est-ext-accepted {
    border-color: #16a34a;
    background: linear-gradient(0deg, #f0fdf4 0%, #ffffff 80%);
  }
  #estimate-content .est-ext-row.est-ext-rejected {
    border-color: #e5e7eb;
    background: #fafafa;
    opacity: 0.65;
  }
  #estimate-content .est-ext-row-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
  }
  #estimate-content .est-status-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #9ca3af;
    flex: 0 0 auto;
  }
  #estimate-content .est-status-dot-not_requested { background: #9ca3af; }
  #estimate-content .est-status-dot-requested     { background: #eab308; }
  #estimate-content .est-status-dot-received      { background: #3b82f6; }
  #estimate-content .est-status-dot-accepted      { background: #16a34a; }
  #estimate-content .est-status-dot-rejected      { background: #dc2626; }
  #estimate-content .est-ext-name {
    flex: 1;
    font-weight: 600;
    font-size: 12.5px;
  }
  #estimate-content .est-ext-status-label {
    font-size: 11px;
    color: var(--text-muted);
    font-weight: 600;
    padding: 2px 8px;
    background: #f3f4f6;
    border-radius: 11px;
  }
  #estimate-content .est-ext-row.est-ext-accepted .est-ext-status-label {
    background: #dcfce7;
    color: #166534;
  }
  #estimate-content .est-ext-row-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 110px 130px;
    gap: 8px;
    margin-bottom: 8px;
  }
  #estimate-content .est-ext-row-grid label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 10.5px;
    color: var(--text-muted);
  }
  #estimate-content .est-ext-row-grid label small {
    font-weight: 400;
    color: var(--text-muted);
    margin-left: 4px;
  }
  #estimate-content .est-ext-row-grid .est-input {
    padding: 5px 8px;
    font-size: 11.5px;
  }
  #estimate-content .est-ext-row-meta {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
    font-size: 10.5px;
    color: var(--text-muted);
    flex-wrap: wrap;
  }
  #estimate-content .est-ext-row-meta b { color: var(--text); }
  #estimate-content .est-ext-actions {
    margin-left: auto;
    display: flex;
    gap: 5px;
    flex-wrap: wrap;
  }
  #estimate-content .est-ext-btn {
    background: var(--btn-sec-bg);
    color: var(--btn-sec-fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 3px 9px;
    font-size: 11px;
    cursor: pointer;
    font-weight: 500;
    transition: background 0.15s ease;
  }
  #estimate-content .est-ext-btn:hover {
    background: var(--btn-bg);
    color: var(--btn-fg);
  }
  #estimate-content .est-ext-btn-primary {
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-weight: 600;
  }
  #estimate-content .est-ext-notes-label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 10.5px;
    color: var(--text-muted);
    margin-bottom: 8px;
  }
  #estimate-content .est-ext-notes-label .est-input {
    padding: 5px 8px;
    font-size: 11.5px;
  }
  #estimate-content .est-ext-attach-area {
    border-top: 1px dashed var(--border);
    padding-top: 8px;
  }
  #estimate-content .est-ext-attach-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
  }
  #estimate-content .est-ext-attach-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: #eff6ff;
    border: 1px solid #bfdbfe;
    border-radius: var(--radius-sm);
    padding: 2px 4px 2px 6px;
    font-size: 11px;
  }
  #estimate-content .est-ext-attach-chip a {
    color: #1e40af;
    text-decoration: none;
  }
  #estimate-content .est-ext-attach-chip a:hover { text-decoration: underline; }
  #estimate-content .est-attach-del {
    background: transparent;
    border: 0;
    color: #64748B;
    cursor: pointer;
    font-size: 14px;
    padding: 0 4px;
    line-height: 1;
    font-weight: 700;
  }
  #estimate-content .est-attach-del:hover { color: #dc2626; }
  #estimate-content .ext-sys-dropzone {
    border: 2px dashed var(--border);
    border-radius: var(--radius-md);
    padding: 12px;
    text-align: center;
    font-size: 11.5px;
    color: var(--text-muted);
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
  }
  #estimate-content .ext-sys-dropzone:hover {
    border-color: var(--btn-bg);
    background: #f8fafc;
  }
  #estimate-content .ext-sys-dropzone.drop-active {
    border-color: #3b82f6;
    background: #eff6ff;
    color: #1e40af;
  }
  #estimate-content .est-dz-icon {
    font-size: 14px;
    margin-right: 4px;
  }
  /* E7 — vaiheet drill-down (kompakti) */
  #estimate-content .est-vaiheet-btn {
    background: var(--btn-sec-bg);
    color: var(--btn-sec-fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 1px 7px;
    font-size: 10.5px;
    font-weight: 600;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
    font-family: 'JetBrains Mono', monospace;
  }
  #estimate-content .est-vaiheet-btn:hover {
    background: var(--btn-bg);
    color: var(--btn-fg);
    border-color: var(--btn-bg);
  }
  #estimate-content .est-vaiheet-detail-tr td.est-vaiheet-detail-td {
    background: #f7f9fc;
    border-bottom: 2px solid var(--border);
    padding: 7px 14px 8px;
  }
  #estimate-content .est-vaiheet-head {
    font-size: 10.5px;
    color: var(--text-muted);
    margin-bottom: 4px;
    font-weight: 500;
  }
  #estimate-content .est-vaiheet-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 11px;
  }
  #estimate-content .est-vaiheet-table td {
    padding: 2px 7px;
    border-bottom: 1px dashed var(--border);
  }
  #estimate-content .est-vaiheet-table tr:last-child td { border-bottom: 0; }
  #estimate-content .est-vaiheet-name {
    min-width: 180px;
    font-weight: 600;
  }
  #estimate-content .est-vaiheet-rooli {
    color: var(--text-muted);
    font-weight: 400;
    font-size: 10px;
  }
  #estimate-content .est-vaiheet-unit {
    width: 60px;
    color: var(--text-muted);
    font-size: 10px;
  }
  #estimate-content .est-vaiheet-yht {
    width: 80px;
    color: var(--text-muted);
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
  }
  #estimate-content .est-vaiheet-eur {
    width: 80px;
    font-weight: 600;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
  }
  #estimate-content .est-vaiheet-foot {
    margin-top: 6px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 10.5px;
    gap: 10px;
  }
  #estimate-content .est-vaiheet-sum {
    color: var(--text);
    font-family: 'JetBrains Mono', monospace;
    font-variant-numeric: tabular-nums;
  }
  #estimate-content .est-reset-btn {
    background: transparent;
    color: var(--text-muted);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 2px 8px;
    font-size: 10px;
    cursor: pointer;
  }
  #estimate-content .est-reset-btn:hover {
    background: #fff7e6;
    color: var(--text);
    border-color: #ffb84a;
  }
  /* Override-näkyvyys: kun käyttäjä on muokannut min-arvon (eri kuin Excelin oletus) */
  #estimate-content .est-input.est-overridden {
    background: #fff9e6;
    border-color: #ffb84a;
    font-weight: 700;
  }
  /* E7b — matkat + päivärahat -osio (Työ-osion sisällä, kompakti) */
  #estimate-content .est-matkat-divider {
    margin: 4px 14px 2px;
    padding: 5px 0 3px;
    border-top: 1px dashed var(--border);
    font-weight: 700;
    font-size: 11.5px;
    color: var(--text);
  }
  #estimate-content .est-matkat-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 14px;
    font-size: 11.5px;
    flex-wrap: wrap;
  }
  #estimate-content .est-matkat-label {
    color: var(--text-muted);
    font-size: 10.5px;
    font-weight: 600;
  }
  #estimate-content .est-matkat-hint {
    color: var(--text-muted);
    font-size: 10px;
    font-style: italic;
    margin-left: auto;
  }
  /* ── 2026-06-30 TIHEYS-PASS (käyttäjä: "kaikki näkyy kerralla, fontit pienemmällä") ──
     Tiivistää estimaattorin pystysuunnassa: pienemmät fontit + tiukemmat välit.
     TARJOUS-otsikko, section-headit ja numerot pysyvät selkeinä (hierarkia säilyy). */
  .est-v2-grid { gap: 12px; }
  /* Vasen palsta — kululaji-osiot */
  #estimate-content .est-section { margin-bottom: 7px; box-shadow: none; }
  #estimate-content .est-section-head { padding: 5px 11px; font-size: 11px; }
  #estimate-content .est-section-meta { font-size: 10px; }
  #estimate-content .est-subsection-head { padding: 3px 11px; font-size: 10px; }
  #estimate-content .est-table { font-size: 11px; }
  #estimate-content .est-table th { font-size: 9px; padding: 3px 8px; }
  #estimate-content .est-table td { padding: 3px 8px; }
  #estimate-content .est-row-tyo { padding: 3px 11px; font-size: 11px; }
  #estimate-content .est-row-tyo .est-tyo-name { flex-basis: 96px; font-size: 11px; }
  #estimate-content .est-row-tyo .est-tyo-detail { font-size: 10px; }
  #estimate-content .est-row-tyo .est-tyo-eur { font-size: 11.5px; min-width: 72px; }
  #estimate-content .est-warnings { padding: 5px 10px; font-size: 10.5px; margin-bottom: 7px; }
  #estimate-content .est-empty { padding: 6px 12px; font-size: 10.5px; }
  #estimate-content .est-ext-toolbar { padding: 5px 10px; font-size: 11px; }
  #estimate-content .est-ext-empty { padding: 12px 14px; font-size: 11px; }
  #estimate-content .est-ext-rows { padding: 6px 10px; }
  #estimate-content .est-input { padding: 1px 4px; font-size: 10.5px; }
  /* Oikea palsta — sticky yhteenveto */
  .est-v2-grid .est-right { padding: 8px 10px; }
  .est-sec { margin-bottom: 7px; }
  .est-sec-head { padding: 6px 10px; font-size: 11.5px; }
  .est-sec-body { padding: 6px 10px 8px; }
  .est-status-strip { margin: 0 0 6px; gap: 6px; }
  .est-chip { padding: 3px 9px; font-size: 10.5px; }
  /* Katteet & tarjous -taulu */
  .est-summary-table { font-size: 11px; }
  .est-summary-table th { padding: 2px 7px; font-size: 9px; }
  .est-summary-table td { padding: 3px 7px; }
  .est-summary-table .est-input { width: 46px !important; font-size: 10.5px !important; }
  .est-summary-total td { font-size: 12px; padding: 5px 8px; }
  .est-summary-total td:last-child { font-size: 14px; }
  /* ── Katteet & tarjous -taulu — KIINTEÄ SARAKERUUDUKKO (impeccable/layout 2026-06-30) ──
     Auto-layout sotki kohdistuksen (otsikot eivät olleet sarakkeidensa päällä). Fixed-grid
     + pieni teksti: jokainen otsikko + numero täsmälleen omassa sarakkeessaan. Rivin hierarkia:
     kustannus → Kate € (vaimennettu, johdettu) → Veroton € (lihava, lopputulos). TARJOUS erotettu. */
  .est-summary-table { table-layout: fixed; font-size: 10.5px; }
  .est-summary-table col.c-label { width: 26%; }
  .est-summary-table col.c-cost  { width: 18%; }
  .est-summary-table col.c-pct   { width: 20%; }
  .est-summary-table col.c-kate  { width: 16%; }
  .est-summary-table col.c-final { width: 20%; }
  .est-summary-table th { padding: 3px 7px; font-size: 8.5px; }
  .est-summary-table td { padding: 3px 7px; }
  .est-summary-table td:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .est-summary-table td.num { white-space: nowrap; }
  .est-summary-table td.num .est-input {
    width: 54px !important; text-align: right; font-size: 10px !important; padding: 1px 5px !important;
    border: 1px solid var(--border); background: var(--panel); border-radius: 5px;
  }
  .est-summary-table td.num .est-input:focus { border-color: var(--btn-bg); box-shadow: 0 0 0 2px rgba(127,168,206,0.22); outline: none; }
  .est-summary-table td.num .est-input::placeholder { color: var(--text-muted); opacity: 0.6; }
  /* Riskivara — kompakti [arvo][% €] mahtuu kate-%-sarakkeeseen */
  .est-summary-table td.num .est-risk-arvo { width: 30px !important; text-align: right; padding: 1px 3px !important; }
  .est-summary-table td.num .est-risk-tyyppi { width: 46px !important; padding: 1px 2px !important; font-size: 9px !important; margin-left: 2px; box-sizing: border-box; }
  /* Rivin hierarkia + total */
  .est-summary-table tbody tr:not(.est-summary-total) td:nth-child(4) { color: var(--text-muted); }
  .est-summary-table tbody tr:not(.est-summary-total) td:nth-child(5) { font-weight: 700; }
  .est-summary-total td { border-top: 2px solid #0F1F3A; font-size: 11px; }
  .est-summary-total td:last-child { font-size: 13px; }

  /* Mallit-modaali */
  #models-grid .ml-product {
    margin-bottom: 22px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    overflow: hidden;
  }
  #models-grid .ml-product-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: linear-gradient(180deg, #fafbfc, #f1f4f8);
    border-bottom: 1px solid var(--border);
  }
  #models-grid .ml-product-title {
    margin: 0;
    font-size: 14px;
    font-weight: 700;
    color: var(--text);
    cursor: pointer;
    flex: 1;
    user-select: none;
    transition: color 0.15s;
  }
  #models-grid .ml-product-title:hover { color: var(--btn-fg); }
  #models-grid .ml-product-count {
    display: inline-block;
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-size: 11px;
    font-weight: 700;
    padding: 1px 8px;
    border-radius: 9px;
    margin-left: 6px;
  }
  #models-grid .ml-review-btn {
    background: var(--btn-bg);
    color: var(--btn-fg);
    border: 0;
    border-radius: var(--radius-md);
    padding: 5px 12px;
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    transition: background 0.15s;
  }
  #models-grid .ml-review-btn:hover { background: var(--btn-bg-hover); }
  #models-grid .ml-thumb-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 12px;
    padding: 14px;
  }
  #models-grid .ml-thumb-card {
    position: relative;
    background: var(--panel);
    border: 1.5px solid var(--border);
    border-radius: var(--radius-lg);
    cursor: pointer;
    overflow: visible;
    transition: border-color 0.15s, box-shadow 0.15s;
    aspect-ratio: 1;
    display: flex;
    flex-direction: column;
  }
  #models-grid .ml-thumb-card:hover {
    border-color: var(--btn-fg);
    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  }
  #models-grid .ml-thumb-img {
    flex: 1;
    width: 100%;
    height: auto;
    min-height: 0;
    object-fit: contain;
    background: var(--panel);
    border-top-left-radius: 7px;
    border-top-right-radius: 7px;
    pointer-events: none;
  }
  #models-grid .ml-thumb-meta {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 4px 7px;
    border-top: 1px solid var(--border);
    background: #fafbfc;
    font-size: 10px;
    font-family: 'JetBrains Mono', monospace;
    color: var(--text-muted);
    border-bottom-left-radius: 7px;
    border-bottom-right-radius: 7px;
  }
  #models-grid .ml-thumb-idx { font-weight: 700; color: var(--text); }
  #models-grid .ml-thumb-size { flex: 1; text-align: right; font-size: 9px; }
  #models-grid .ml-thumb-del {
    position: absolute;
    top: -7px;
    right: -7px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 0;
    background: #dc2626;
    color: #fff;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
    font-weight: 700;
    padding: 0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
    opacity: 0;
    transition: opacity 0.15s;
  }
  #models-grid .ml-thumb-card:hover .ml-thumb-del { opacity: 1; }
  #models-grid .ml-thumb-del:hover { background: #b91c1c; }
  #models-grid .ml-loading,
  #models-grid .ml-empty {
    text-align: center;
    padding: 60px 20px;
    color: var(--text-muted);
    font-size: 13px;
  }
  /* Sarjatarkistus-bannieri vektorimuokkausmodaalin yläosaan.
     2026-07-09: iso N/M-laskuri + edistymispalkki — käyttäjäpalaute
     "ei tue tarpeeksi selkeästi että on 1/4, 2/4 menossa". */
  #modal-bg.models-reviewing #modal-head h2 {
    background: var(--btn-bg);
    color: var(--btn-fg);
    padding: 5px 10px 7px;
    border-radius: 5px;
    font-size: 13px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    position: relative;
  }
  #modal-bg.models-reviewing .mrv-count {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 16px;
    font-weight: 800;
    background: var(--canvas-accent, #1565C0);
    color: #fff;
    padding: 1px 8px;
    border-radius: 5px;
    line-height: 1.4;
  }
  #modal-bg.models-reviewing .mrv-text { font-weight: 600; }
  #modal-bg.models-reviewing .mrv-bar {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 3px;
    background: rgba(0, 0, 0, 0.12);
    border-radius: 0 0 5px 5px;
    overflow: hidden;
  }
  #modal-bg.models-reviewing .mrv-bar-fill {
    display: block;
    height: 100%;
    background: var(--canvas-accent, #1565C0);
  }

  #vek-admin-btn{ display:none; position:fixed; right:14px; bottom:14px; z-index:9000;
    background:#0F1F3A; color:#fff; border:none; border-radius:10px; padding:9px 14px;
    font-size:13px; font-weight:600; cursor:pointer; box-shadow:0 4px 14px rgba(15,31,58,.25); }
  body.is-admin #vek-admin-btn{ display:block; }
  #vek-admin-bg{ display:none; position:fixed; inset:0; background:rgba(15,31,58,.45); z-index:9001;
    align-items:center; justify-content:center; }
  #vek-admin-bg.open{ display:flex; }
  #vek-admin{ background:#fff; border-radius:14px; width:min(1180px,96vw); max-height:92vh; overflow:auto;
    box-shadow:0 12px 40px rgba(15,31,58,.3); }
  #vek-admin .va-head{ display:flex; align-items:center; justify-content:space-between;
    padding:16px 20px; border-bottom:1px solid #E8EDF3; position:sticky; top:0; background:#fff; }
  #vek-admin h3{ margin:0; font-size:16px; color:#0F1F3A; }
  #vek-admin .va-body{ padding:14px 20px 20px; }
  #vek-admin table{ width:100%; border-collapse:collapse; font-size:12px; }
  #vek-admin th,#vek-admin td{ padding:6px 7px; border-bottom:1px solid #EEF2F7; text-align:center; white-space:nowrap; }
  #vek-admin th.user,#vek-admin td.user{ text-align:left; position:sticky; left:0; background:#fff; }
  #vek-admin th{ font-weight:600; color:#475569; font-size:11px; }
  #vek-admin .va-on{ color:#067647; font-weight:700; } #vek-admin .va-off{ color:#cbd5e1; }
  #vek-admin .va-basic{ background:#F5F7FA; }
  #vek-admin input[type=checkbox]{ cursor:pointer; }
  #vek-admin .va-close{ background:#DBE5F0; color:#1E2F4A; border:none; border-radius:8px; padding:7px 13px; cursor:pointer; font-weight:600; }
  #vek-admin .va-hint{ font-size:12px; color:#64748B; margin:0 0 12px; }
  /* 2026-07-02 #20: ryhmitelty lista-asettelu (19 lippua ei mahdu sarakkeiksi) */
  #vek-admin .va-user{ border:1px solid #E8EDF3; border-radius:10px; padding:10px 14px 12px; margin-bottom:10px; }
  #vek-admin .va-user-head{ display:flex; align-items:baseline; gap:10px; margin-bottom:6px; }
  #vek-admin .va-user-head b{ font-size:13px; color:#0F1F3A; }
  #vek-admin .va-user-head .va-count{ font-size:11px; color:#64748B; font-family:ui-monospace,monospace; }
  /* 2026-07-25 myyntikatselmus A7: tilaustila + massatoiminnot asiakaskortille.
     Ilman näitä aktivointi oli SQL-editori + ~15 ruksia käsin. */
  #vek-admin .va-sub{ display:flex; align-items:center; gap:10px; font-size:11.5px; font-weight:600;
    color:#475569; margin:0 0 8px; }
  #vek-admin .va-sub-active{ color:#15803D; }
  #vek-admin .va-sub-trialing{ color:#B45309; }
  #vek-admin .va-sub-canceled, #vek-admin .va-sub-none{ color:#B42318; }
  #vek-admin .va-presets{ display:flex; gap:6px; margin:0 0 10px; }
  #vek-admin .va-act{ font:600 11.5px/1 inherit; padding:6px 11px; border-radius:8px;
    border:1px solid #E8EDF3; background:#DBE5F0; color:#1E2F4A; cursor:pointer; }
  #vek-admin .va-act:hover{ background:#C2D2E5; }
  #vek-admin .va-act:disabled{ opacity:.55; cursor:default; }
  #vek-admin .va-groups{ display:flex; flex-wrap:wrap; gap:6px 22px; }
  #vek-admin .va-group{ min-width:200px; }
  #vek-admin .va-group-title{ font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:#64748B; margin:4px 0 3px; }
  #vek-admin .va-chip{ display:inline-flex; align-items:center; gap:5px; border:1px solid #E8EDF3; border-radius:8px; padding:3px 8px; margin:2px 3px 2px 0; font-size:12px; color:#0F1F3A; cursor:pointer; user-select:none; }
  #vek-admin .va-chip.va-basic{ background:#F5F7FA; }
  #vek-admin .va-chip:hover{ border-color:#94A3B8; }
  body.theme-dark #vek-admin .va-user{ border-color:var(--border); }
  body.theme-dark #vek-admin .va-chip{ border-color:var(--border); color:var(--text); }
  body.theme-dark #vek-admin .va-chip.va-basic{ background:var(--panel-soft); }

  /* 2026-06-30: Tili siirretty oikean yläkulman avatariksi (käyttäjäpyyntö, Countfire-tyyli; oli vasen alakulma) */
  /* 2026-07-25 flow-katselmus D22: kokeilun paattymisen estoruutu (#vek-block)
     on z-index 9500. Tilinhallinta jai sen ALLE (9050/9051/9002/9001), joten
     GDPR-tietovienti ja tilin poisto olivat estoruudun peitossa — vaikka koodi
     itse linjaa etta ne EIVAT saa olla maksumuurin takana. Nostettu estoruudun
     ylapuolelle; estoruutu itse EI muutu. */
  #vek-acct-btn{ display:none; position:fixed; top:7px; right:10px; z-index:9600; width:34px; height:34px; align-items:center; justify-content:center; background:#334155; color:#fff; border:1px solid rgba(255,255,255,.25); border-radius:50%; padding:0; font-size:14px; font-weight:700; cursor:pointer; box-shadow:0 4px 14px rgba(15,31,58,.35); }
  #vek-acct-btn:hover{ background:#3E4C63; }
  #vek-acct-menu{ display:none; position:fixed; top:48px; right:10px; z-index:9601; background:#fff; border:1px solid #E8EDF3; border-radius:10px; box-shadow:0 8px 24px rgba(15,31,58,.18); overflow:hidden; }
  #vek-acct-menu button{ display:block; width:100%; text-align:left; background:none; border:none; padding:10px 16px; font-size:13px; color:#1E2F4A; cursor:pointer; white-space:nowrap; }
  #vek-acct-menu button:hover{ background:#F1F5F9; }
  #vek-acct-menu #vek-acct-name-save:hover{ background:#C2D2E5; }
  #vek-acct-profile{ padding:12px 16px; border-bottom:1px solid #E8EDF3; min-width:240px; }
  #vek-acct-profile .vap-cap{ font-size:10.5px; text-transform:uppercase; letter-spacing:.05em; color:#64748B; font-weight:700; margin-bottom:3px; }
  #vek-acct-profile .vap-email{ font-size:13px; font-weight:600; color:#0F1F3A; word-break:break-all; }
  #vek-acct-profile .vap-meta{ font-size:11.5px; color:#64748B; margin-top:2px; }
  #vek-acct-profile .vap-namerow{ display:flex; gap:6px; margin-top:9px; align-items:center; }
  #vek-acct-profile .vap-namerow input{ flex:1; min-width:0; padding:6px 9px; border:1px solid #E8EDF3; border-radius:7px; font-size:12.5px; font-family:inherit; color:#0F1F3A; outline:none; }
  #vek-acct-profile .vap-namerow input:focus{ border-color:#0F1F3A; }
  #vek-acct-menu #vek-acct-name-save{ display:inline-block; width:auto; padding:6px 12px; background:#DBE5F0; color:#1E2F4A; border:0; border-radius:7px; font-size:12.5px; font-weight:600; cursor:pointer; }
  #vek-acct-profile .vap-msg{ font-size:11px; margin-top:6px; display:none; }
  #vek-pw-bg{ display:none; position:fixed; inset:0; background:rgba(15,31,58,.45); z-index:9602; align-items:center; justify-content:center; }
  #vek-pw-bg.open{ display:flex; }
  #vek-pw{ background:#fff; border-radius:14px; width:min(380px,92vw); padding:24px; box-shadow:0 12px 40px rgba(15,31,58,.3); }
  #vek-pw h3{ margin:0 0 6px; font-size:16px; color:#0F1F3A; }
  #vek-pw label{ display:block; font-size:12.5px; font-weight:600; color:#475569; margin:12px 0 5px; }
  #vek-pw input{ width:100%; padding:10px 12px; border:1px solid #E8EDF3; border-radius:9px; font-size:14px; box-sizing:border-box; }
  #vek-pw .row{ display:flex; gap:8px; margin-top:18px; }
  #vek-pw .row button{ flex:1; padding:10px; border:none; border-radius:9px; font-weight:600; cursor:pointer; }
  #vek-pw .save{ background:#DBE5F0; color:#1E2F4A; } #vek-pw .cancel{ background:#F1F5F9; color:#475569; }
  #vek-pw .msg{ margin-top:12px; font-size:12.5px; display:none; } #vek-pw .msg.err{ display:block; color:#B42318; } #vek-pw .msg.ok{ display:block; color:#067647; }
  /* 2026-06-27: #vek-reg-CSS poistettu — rekisteri siirretty ⚙ Asetukset → Tuotteet & hinnasto (omat .set-* -tyylit). */

  /* ── 2026-07-09 Oma tili -näkymä (#tili-bg): sama modaalikuvio kuin #vek-pw-bg (overlay + .open),
     navy-otsikko kuten settings-modaalissa, .set-sec-tyyliset osiot (.tili-sec). ── */
  #tili-bg{ display:none; position:fixed; inset:0; background:rgba(15,31,58,.45); z-index:9603; align-items:center; justify-content:center; padding:20px; }
  #tili-bg.open{ display:flex; }
  #tili{ background:#fff; border-radius:14px; width:min(560px,94vw); max-height:88vh; display:flex; flex-direction:column; overflow:hidden; box-shadow:0 12px 40px rgba(15,31,58,.3); }
  .tili-head{ background:var(--navy,#334155); color:#fff; padding:13px 18px; display:flex; align-items:center; gap:12px; flex-shrink:0; }
  .tili-head h2{ margin:0; font-size:15px; letter-spacing:-0.1px; flex:1; }
  .tili-head #tili-close{ background:transparent; color:#fff; border:1px solid rgba(255,255,255,.35); border-radius:6px; width:26px; height:26px; line-height:1; font-size:15px; cursor:pointer; }
  .tili-body{ padding:14px 18px; overflow-y:auto; }
  .tili-sec{ border:1px solid var(--border,#E8EDF3); border-radius:11px; margin-bottom:12px; overflow:hidden; background:var(--panel,#fff); }
  .tili-sec:last-child{ margin-bottom:0; }
  .tili-sec-h{ font-size:11px; font-weight:700; letter-spacing:0.4px; text-transform:uppercase; color:var(--text-muted,#94A3B8); padding:9px 13px; background:var(--bg,#FAFAF7); border-bottom:1px solid var(--border,#E8EDF3); }
  .tili-sec-b{ padding:12px 13px; }
  .tili-row{ display:flex; align-items:baseline; gap:10px; margin-bottom:8px; }
  .tili-lang-row{ align-items:center; justify-content:space-between; margin-bottom:0; }
  .tili-lang-row .rb-unit-toggle{ margin-right:0; }
  .tili-label{ font-size:11.5px; font-weight:600; color:#475569; flex-shrink:0; }
  .tili-val{ font-size:13px; font-weight:600; color:#0F1F3A; word-break:break-all; }
  .tili-note{ font-size:11.5px; color:var(--text-soft,#5C5C61); margin:0 0 9px; line-height:1.5; }
  .tili-namerow{ display:flex; gap:6px; align-items:center; }
  .tili-namerow input{ flex:1; min-width:0; padding:7px 10px; border:1px solid var(--border,#E8EDF3); border-radius:7px; font-size:12.5px; font-family:inherit; color:#0F1F3A; outline:none; }
  .tili-namerow input:focus{ border-color:#0F1F3A; }
  .tili-namerow button{ flex-shrink:0; padding:7px 13px; background:#DBE5F0; color:#1E2F4A; border:0; border-radius:7px; font-size:12.5px; font-weight:600; cursor:pointer; }
  .tili-namerow button:hover{ background:#C2D2E5; }
  .tili-namerow button:disabled{ opacity:.5; cursor:default; }
  .tili-btn{ display:inline-block; padding:8px 14px; background:var(--btn-sec-bg,#F1F5F9); color:var(--btn-sec-fg,#475569); border:1px solid var(--border,#E8EDF3); border-radius:9px; font-size:12.5px; font-weight:600; cursor:pointer; }
  .tili-btn:hover{ background:#E2E8F0; }
  .tili-msg{ font-size:11.5px; margin-top:7px; display:none; line-height:1.45; }
  .tili-msg.err{ display:block; color:#B42318; }
  .tili-msg.ok{ display:block; color:#067647; }
  /* Vaarallinen alue — punasävyt kuten vanhassa settings-acct-del-napissa (#FEE2E2/#B42318/#FDA29B) */
  .tili-danger .tili-sec-h{ color:#B42318; background:#FEF2F2; border-bottom-color:#FDA29B; }
  .tili-danger{ border-color:#FDA29B; }
  .tili-danger .tili-namerow input:focus{ border-color:#B42318; }
  .tili-danger #tili-del{ background:#FEE2E2; color:#B42318; border:1px solid #FDA29B; }
  .tili-danger #tili-del:hover:not(:disabled){ background:#FECACA; }
  .tili-danger #tili-del:disabled{ opacity:.45; cursor:default; }
/* HUB-revisiot (2026-07-11) — "Rev N" -merkki kortissa + projektisivun revisiovalitsin
   + uusi-revisio-prompt. Vain UI-kerros; teematokenit → toimii vaalea/tumma. */

/* ── Grid-kortin "Rev N" -merkki (ryhmäkortti = uusin revisio) ── */
.hc-rev-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  background: var(--navy, #334155);
  border-radius: 999px;
  box-shadow: 0 1px 3px rgba(15, 31, 58, 0.25);
  pointer-events: none;
}

/* ── Projektisivun revisiovalitsin ── */
.hd-revbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 2px 0 14px;
}
.hd-revpills {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--btn-sec-bg, #F1F5F9);
  border: 1px solid var(--border, #E8EDF3);
  border-radius: 12px;
}
.hd-revpill {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--btn-sec-fg, #475569);
  font-size: 12.5px;
  font-weight: 600;
  padding: 6px 14px;
  border-radius: 9px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s ease, color 0.12s ease;
}
.hd-revpill:hover {
  color: var(--text, #0F1F3A);
  background: rgba(15, 31, 58, 0.05);
}
.hd-revpill.active {
  color: #fff;
  background: var(--navy, #334155);
  box-shadow: 0 1px 2px rgba(15, 31, 58, 0.18);
  cursor: default;
}
.hd-revnew {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 13px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--btn-fg, #1E2F4A);
  background: var(--btn-bg, #DBE5F0);
  border: 1px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.12s ease;
}
.hd-revnew:hover {
  background: var(--btn-bg-hover, #C2D2E5);
}
.hd-revnew svg {
  flex: 0 0 auto;
}

/* ── Uusi-revisio-prompt (pieni modaali) ── */
.rev-prompt-bg {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 31, 58, 0.38);
  backdrop-filter: blur(2px);
}
.rev-prompt {
  width: min(92vw, 380px);
  background: var(--panel, #fff);
  border: 1px solid var(--border, #E8EDF3);
  border-radius: 14px;
  box-shadow: 0 18px 48px rgba(15, 31, 58, 0.28);
  padding: 20px;
}
.rev-prompt-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text, #0F1F3A);
  margin-bottom: 12px;
}
.rev-prompt-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  font-size: 14px;
  color: var(--text, #0F1F3A);
  background: var(--bg, #FAFAF7);
  border: 1px solid var(--border, #E8EDF3);
  border-radius: 10px;
  outline: none;
}
.rev-prompt-input:focus {
  border-color: var(--navy, #334155);
}
.rev-prompt-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}
.rev-prompt-cancel,
.rev-prompt-ok {
  appearance: none;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 10px;
  cursor: pointer;
  border: 1px solid transparent;
}
.rev-prompt-cancel {
  color: var(--btn-sec-fg, #475569);
  background: var(--btn-sec-bg, #F1F5F9);
  border-color: var(--border, #E8EDF3);
}
.rev-prompt-cancel:hover {
  background: #E9EEF4;
}
.rev-prompt-ok {
  color: #fff;
  background: var(--navy, #334155);
}
.rev-prompt-ok:hover {
  filter: brightness(1.08);
}

/* ── Revisiovertailu: base-piirustuksen dropdown + "tuo laskenta" -nappi diff-paneelissa ── */
.dp-base-sel {
  max-width: 190px;
  padding: 2px 6px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text, #0F1F3A);
  background: var(--panel, #fff);
  border: 1px solid var(--border, #E8EDF3);
  border-radius: 7px;
  cursor: pointer;
  vertical-align: middle;
}
.dp-carry {
  display: block;
  width: 100%;
  margin: 8px 0 4px;
  padding: 8px 10px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--btn-fg, #1E2F4A);
  background: var(--btn-bg, #DBE5F0);
  border: 1px solid transparent;
  border-radius: 9px;
  cursor: pointer;
  transition: background 0.12s ease;
}
.dp-carry:hover {
  background: var(--btn-bg-hover, #C2D2E5);
}
/* Symbolikirjasto: rajattu modal-tyyli. Ei vaikuta muihin näkymiin tai modaaleihin. */
#library-bg {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(15, 31, 58, 0.48);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

#library-bg.is-open {
  display: flex;
}

#library-modal {
  --library-danger: #b42318;
  --library-focus: #1687bd;
  display: flex;
  width: min(1460px, 96vw);
  height: min(900px, 92vh);
  min-width: 0;
  min-height: 0;
  flex-direction: column;
  overflow: hidden;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 24px 70px rgba(6, 18, 36, 0.28);
}

#library-modal *,
#library-modal *::before,
#library-modal *::after {
  box-sizing: border-box;
}

#library-modal [hidden] {
  display: none;
}

#library-modal button,
#library-modal input,
#library-modal select {
  font: inherit;
}

#library-modal button {
  color: var(--text);
}

#library-modal button:focus-visible,
#library-modal input:focus-visible,
#library-modal select:focus-visible,
#library-modal [tabindex]:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--library-focus) 40%, transparent);
  outline-offset: 2px;
}

#library-modal button:disabled {
  cursor: not-allowed;
  opacity: 0.48;
}

#library-modal .library-header {
  position: relative;
  display: flex;
  min-height: 70px;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 14px 20px;
  color: var(--text);
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}

#library-modal .library-heading {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 12px;
}

#library-modal .library-heading-icon {
  display: grid;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  place-items: center;
  color: var(--blue);
  background: color-mix(in srgb, var(--blue) 12%, var(--panel));
  border-radius: 10px;
}

#library-modal #library-title {
  margin: 0;
  color: var(--text);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.25;
}

#library-modal #library-summary {
  display: block;
  min-height: 17px;
  margin-top: 3px;
  color: var(--text-muted);
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
}

#library-modal .library-header-actions {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 8px;
}

#library-modal .library-maintenance {
  position: relative;
}

#library-modal #library-maintenance-btn,
#library-modal #library-close,
#library-modal #library-filter-reset,
#library-modal #library-siivous-bar button,
#library-modal #library-footer button {
  min-height: 36px;
  padding: 7px 12px;
  cursor: pointer;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px;
  font-weight: 650;
}

#library-modal #library-maintenance-btn:hover,
#library-modal #library-close:hover,
#library-modal #library-filter-reset:hover {
  background: var(--panel-soft);
}

#library-modal #library-footer button:not(#library-import-all):hover,
#library-modal #library-siivous-bar button:not(#library-siivous-delete):hover {
  background: var(--panel-soft);
}

#library-modal #library-maintenance-btn[aria-expanded="true"] {
  color: var(--blue);
  border-color: var(--blue);
}

#library-modal #library-close {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

#library-modal #library-maintenance-menu {
  position: absolute;
  z-index: 2;
  top: calc(100% + 7px);
  right: 0;
  width: 210px;
  padding: 6px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 14px 32px rgba(6, 18, 36, 0.2);
}

#library-modal #library-maintenance-menu button {
  display: block;
  width: 100%;
  padding: 9px 10px;
  cursor: pointer;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 7px;
  font-size: 12px;
}

#library-modal #library-maintenance-menu button:hover,
#library-modal #library-maintenance-menu button:focus-visible {
  background: var(--panel-soft);
}

#library-modal .library-filters {
  display: grid;
  grid-template-columns: minmax(240px, 1.5fr) repeat(3, minmax(150px, 1fr)) auto;
  flex: 0 0 auto;
  align-items: end;
  gap: 12px;
  padding: 12px 20px 14px;
  background: var(--panel-soft);
  border-bottom: 1px solid var(--border);
}

#library-modal .library-filter-field {
  display: grid;
  min-width: 0;
  gap: 5px;
}

#library-modal .library-filter-field label {
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 750;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

#library-modal select,
#library-modal input {
  width: 100%;
  min-width: 0;
  height: 38px;
  padding: 7px 10px;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
}

#library-modal select option {
  color: #182230;
  background: #ffffff;
}

body.theme-dark #library-modal select option {
  color: #eef4ff;
  background: #17202e;
}

#library-modal #library-filter-reset {
  white-space: nowrap;
}

#library-modal #library-siivous-bar {
  display: flex;
  flex: 0 0 auto;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  color: #5f3d00;
  background: #fff8d7;
  border-bottom: 1px solid #ead38c;
  font-size: 12px;
}

#library-modal #library-siivous-bar strong {
  margin-right: 4px;
}

#library-modal #library-siivous-delete {
  margin-left: auto;
  color: #fff;
  background: var(--library-danger);
  border-color: var(--library-danger);
}

#library-modal #library-siivous-error {
  width: 100%;
  margin: 2px 0 0;
  color: #8f1710;
  font-weight: 650;
}

#library-modal #library-info-banner {
  flex: 0 0 auto;
  padding: 10px 20px;
  color: #0c4a6e;
  background: #eff9ff;
  border-bottom: 1px solid #b9e2f7;
  font-size: 12px;
  line-height: 1.5;
}

#library-modal .library-content {
  display: grid;
  min-width: 0;
  min-height: 0;
  grid-template-columns: minmax(300px, 360px) minmax(0, 1fr);
  flex: 1 1 auto;
  overflow: hidden;
}

#library-modal #library-product-list,
#library-modal #library-variant-grid {
  min-width: 0;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
}

#library-modal #library-product-list {
  padding: 10px;
  background: var(--bg);
  border-right: 1px solid var(--border);
}

#library-modal #library-variant-grid {
  padding: 22px;
  background: var(--panel);
}

#library-modal .library-empty-state,
#library-modal .library-load-state {
  display: grid;
  min-height: 220px;
  place-content: center;
  padding: 28px;
  color: var(--text-muted);
  text-align: center;
  font-size: 13px;
  line-height: 1.65;
}

#library-modal .library-empty-state button,
#library-modal .library-load-state button {
  justify-self: center;
  margin-top: 14px;
  padding: 8px 13px;
  cursor: pointer;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
}

#library-modal .lib-prod-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  margin-bottom: 7px;
  padding: 11px 12px;
  cursor: pointer;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 9px;
}

#library-modal .lib-prod-row.has-cleanup {
  grid-template-columns: auto minmax(0, 1fr) auto;
}

#library-modal .lib-prod-row:hover {
  border-color: color-mix(in srgb, var(--blue) 45%, var(--border));
}

#library-modal .lib-prod-row.is-active {
  background: color-mix(in srgb, var(--blue) 9%, var(--panel));
  border-color: var(--blue);
}

#library-modal .lib-prod-main {
  display: flex;
  width: 100%;
  min-width: 0;
  align-items: flex-start;
  gap: 9px;
  padding: 0;
  cursor: pointer;
  text-align: left;
  background: transparent;
  border: 0;
}

#library-modal .lib-prod-copy {
  display: block;
  min-width: 0;
}

#library-modal .lib-prod-name {
  display: block;
  overflow: hidden;
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#library-modal .lib-prod-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-top: 6px;
  color: var(--text-muted);
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
}

#library-modal .lib-prod-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 7px;
}

#library-modal .library-badge {
  display: inline-flex;
  align-items: center;
  min-height: 20px;
  padding: 2px 7px;
  color: var(--text-muted);
  background: var(--panel-soft);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 9px;
  font-weight: 700;
  line-height: 1.2;
}

#library-modal .library-badge.is-ready {
  color: #146b3a;
  background: #eaf8ef;
  border-color: #a7ddb9;
}

#library-modal .library-badge.is-warning {
  color: #7a4d00;
  background: #fff7db;
  border-color: #e7cf86;
}

#library-modal .library-badge.is-muted {
  color: var(--text-muted);
}

#library-modal .lib-prod-actions {
  display: flex;
  align-items: flex-start;
  gap: 3px;
}

#library-modal .lib-prod-action {
  display: grid;
  width: 30px;
  height: 30px;
  padding: 0;
  cursor: pointer;
  place-items: center;
  color: var(--text-muted);
  background: transparent;
  border: 0;
  border-radius: 6px;
}

#library-modal .lib-prod-action:hover {
  color: var(--text);
  background: var(--panel-soft);
}

#library-modal .lib-prod-action.is-danger {
  color: var(--library-danger);
}

#library-modal .lib-cleanup-check {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  margin: 2px 0 0;
  cursor: pointer;
}

#library-modal #library-footer {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  background: var(--panel-soft);
  border-top: 1px solid var(--border);
}

#library-modal #library-footer-info {
  min-width: 0;
  flex: 1 1 auto;
  color: var(--text-muted);
  font-size: 11px;
}

#library-modal #library-import-all {
  color: #fff;
  background: var(--navy);
  border-color: var(--navy);
}

#library-modal #library-footer #library-import-all:hover {
  color: #fff;
  background: color-mix(in srgb, var(--navy) 84%, #ffffff);
  border-color: color-mix(in srgb, var(--navy) 84%, #ffffff);
}

#library-modal #library-siivous-bar #library-siivous-delete:hover {
  color: #fff;
  background: #8f1710;
  border-color: #8f1710;
}

#library-modal #library-maintenance-menu[hidden],
#library-modal #library-filter-reset[hidden],
#library-modal #library-siivous-bar[hidden],
#library-modal #library-siivous-error[hidden],
#library-modal #library-info-banner[hidden],
#library-modal #library-footer[hidden] {
  display: none;
}

body.theme-dark #library-modal .library-badge.is-ready {
  color: #b7f0ca;
  background: #153b27;
  border-color: #2d7048;
}

body.theme-dark #library-modal .library-badge.is-warning,
body.theme-dark #library-modal #library-siivous-bar {
  color: #f7dda0;
  background: #3b3118;
  border-color: #6c5926;
}

body.theme-dark #library-modal #library-info-banner {
  color: #b8e5fa;
  background: #153243;
  border-color: #285b74;
}

body.theme-dark #library-modal #library-siivous-error {
  color: #fecaca;
}

@media (max-width: 1100px) {
  #library-modal .library-filters {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  #library-modal #library-filter-reset {
    justify-self: start;
  }

  #library-modal .library-content {
    grid-template-columns: minmax(270px, 320px) minmax(0, 1fr);
  }
}

@media (max-width: 760px) {
  #library-bg {
    padding: 8px;
  }

  #library-modal {
    width: 100%;
    height: 98vh;
    border-radius: 11px;
  }

  #library-modal .library-header {
    align-items: flex-start;
    padding: 12px;
  }

  #library-modal #library-close span {
    display: none;
  }

  #library-modal .library-filters {
    grid-template-columns: 1fr;
    padding: 10px 12px;
  }

  #library-modal .library-content {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(170px, 42%) minmax(0, 1fr);
  }

  #library-modal #library-product-list {
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }

  #library-modal #library-variant-grid {
    padding: 14px;
  }

  #library-modal #library-footer {
    flex-wrap: wrap;
    padding: 10px 12px;
  }

  #library-modal #library-footer-info {
    width: 100%;
    flex-basis: 100%;
  }
}

@media (min-width: 1200px) and (max-height: 800px) {
  #library-bg {
    padding: 12px;
  }

  #library-modal {
    height: 96vh;
  }

  #library-modal .library-header {
    min-height: 60px;
    padding-top: 10px;
    padding-bottom: 10px;
  }

  #library-modal .library-filters {
    padding-top: 9px;
    padding-bottom: 10px;
  }
}
