/* e1a.css -- editor-kern. Vervangt de POC-invulling; de metingen (contain: strict, GEEN
 * content-visibility) blijven gelden -- zie e1a.js.
 *
 * ALLES STAAT ONDER #code. Een kale .sel of .ln raakte elke module die dezelfde korte
 * klassenaam koos (de verkenner: .row.sel kreeg pointer-events: none en was niet meer
 * klikbaar). De tokenklassen .k .t .i .c .m .s .n komen uit e1b en gelden ook alleen hier;
 * wie ze elders gebruikt (e9b's helppaneel) kleurt ze zelf. De tabstrip is van e3b. */

/* DE LETTERGROOTTE van de editor is --code-fs/--line-h uit core.css, gezet door Settings
 * (editor.fontsize, e5b.js). Alles groter maken doet de browserzoom. */
#editor {
  display: grid; grid-template-columns: auto 1fr;
  font: var(--code-fs)/var(--line-h) var(--font-code);
  position: relative;
  min-height: 0;
}
#editor .empty {
  grid-column: 1 / 3; display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); font: var(--ui-fs) var(--font-ui);
}
#editor .empty[hidden] { display: none; }
/* #gutter STAAT IN #viewport, als eerste kolom naast #code (S-0000-0312): EEN
 * scrollcontainer voor regelnummers en tekst, dus ze kunnen niet uiteenlopen -- niet
 * onderaan (60vh voorbij-het-einde), niet tijdens een compositor-scroll, en een muiswiel
 * boven de nummers scrolt gewoon de tekst. Hij rekt mee met #code (grid-stretch), dus zijn
 * achtergrond loopt door tot onderaan; sticky left houdt hem op zijn plek als de tekst ooit
 * horizontaal scrolt. Geen eigen overflow: hij is geen scrollcontainer meer. */
#gutter {
  background: var(--bg); color: var(--text-muted);
  text-align: right; padding: 8px 10px 8px 14px; min-width: 56px;
  white-space: pre;
  position: sticky; left: 0; z-index: 1;
}
/* DE MARKERS IN DE GUTTER STAAN OP DE BASISLIJN VAN HET REGELNUMMER (S-0000-0312).
 * Een .g is een flexrij, rechts uitgelijnd, align-items: baseline. Een marker (de
 * breekpuntstip en de pijl van dbg.css, het lampje van slim.css) is een doosje van
 * hoogte H met margin-top: -H: hij neemt dan GEEN hoogte in (de regel blijft precies
 * --line-h hoog), en zijn onderkant ligt op de basislijn van het cijfer. Daarna
 * transform: translateY(calc(H/2 - var(--gcap)/2)): het midden van de marker komt op het midden
 * van het cijfer (basislijn min een halve kapitaalhoogte). Eerder stond de stip op
 * top: 50% van de regelbox -- en of dat het midden van het CIJFER is, hangt af van de
 * verhouding ascent/descent van het font: met een font dat onderaan veel ruimte houdt
 * zakte de stip zichtbaar onder het cijfer. De basislijn beweegt mee met elk font, elke
 * lettergrootte en elke zoomstand; een vaste top doet dat niet.
 * --gcap is geregistreerd (<length>) zodat hij op de .g zelf naar px wordt uitgerekend
 * en zo overerft -- het lampje heeft een eigen, kleinere letter, maar hoort op het cijfer. */
@property --gcap { syntax: "<length>"; inherits: true; initial-value: 10px; }
#gutter .g {
  display: flex; justify-content: flex-end; align-items: baseline; column-gap: 3px;
  --gcap: .72em;
}
@supports (height: 1cap) { #gutter .g { --gcap: 1cap; } }
#gutter .g.cur { color: var(--text); }
#gutter .g.mark-error { color: var(--danger); }

/* #viewport is de scrollcontainer; #code erbinnen krijgt bij windowing zijn ware hoogte
   (regels * regelhoogte) zodat de scrollbar de echte lengte toont, met alleen het
   zichtbare venster + marge als kinderen -- zie drawWindow() in e1a.js. */
#viewport {
  grid-column: 1 / -1;
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: stretch;
  overflow: auto; min-height: 0; min-width: 0;
  scrollbar-color: var(--rule) transparent;
  scrollbar-width: thin;
}
#code {
  padding: 8px 0 60vh 8px;
  outline: 0; white-space: pre; min-width: 0;
  color: var(--text);
  position: relative;
}
#code.windowed { padding-top: 0; }
#code.windowed .ln { position: absolute; left: 0; right: 0; }

#code .ln {
  height: var(--line-h); padding: 0 8px;
  /* contain: strict -- gemeten in de POC: aanslag 12,1 ms -> 0,4 ms. content-visibility:
     auto is geprobeerd en maakte het twee keer trager (8,5 -> 17,3 ms). Laat dit staan. */
  contain: strict; width: 100%;
  position: relative;
}
#code .ln.cur { background: var(--curline); }
/* DE GOLFLIJN IS EEN LAAG ONDERIN DE REGEL, geen text-decoration (S-0000-0309). Een
 * underline wavy staat een paar pixels onder de basislijn en loopt dan UIT de regelbox --
 * en contain: strict (paint-containment, hierboven) knipt alles buiten die box weg: de
 * golf was half of helemaal onzichtbaar, afhankelijk van het font. Zoals VS Code: een
 * herhaalde golf van 6x3 onderin de regelbox (bottom: 0), dus altijd onder de basislijn
 * en altijd binnen de box. Hij loopt van de eerste niet-spatie tot het regeleinde
 * (--mark-x/--mark-w, gezet door markGeom in e1a.js), minimaal een teken, zodat een fout op een lege regel zichtbaar
 * blijft. Kleur via mask, zodat het thema (--danger/--attn) hem bepaalt. */
#code .ln.mark-error::after,
#code .ln.mark-warning::after {
  content: ""; position: absolute; left: calc(8px + var(--mark-x, 0px)); bottom: 0; height: 3px;
  width: max(var(--mark-w, 100%), 1ch);
  pointer-events: none;
  -webkit-mask: var(--squiggle) repeat-x left bottom / 6px 3px;
  mask: var(--squiggle) repeat-x left bottom / 6px 3px;
}
#code .ln.mark-error::after { background: var(--danger); }
#code .ln.mark-warning::after { background: var(--attn); }
#code {
  --squiggle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 3' width='6' height='3'%3E%3Cg fill='%23000'%3E%3Cpolygon points='5.5,0 2.5,3 1.1,3 4.1,0'/%3E%3Cpolygon points='4,0 6,2 6,0.6 5.4,0'/%3E%3Cpolygon points='0,2 1,3 2.4,3 0,0.6'/%3E%3C/g%3E%3C/svg%3E");
}
#code .k { color: var(--syn-keyword); }
#code .t { color: var(--syn-type); }
#code .i { color: var(--syn-ident); }
#code .c { color: var(--syn-const); }
#code .m { color: var(--syn-comment); font-style: italic; }
#code .s { color: var(--syn-string); }
#code .n { color: var(--syn-number); }

/* SELECTIE: een overlay-<div> per geraakte regel (gedeeltelijk) of een class (volledig),
   geen span per teken -- zie drawSel() in e1a.js. Kleur wijkt tussen actief/inactief
   venster, zoals VS Code. */
#code .sel {
  position: absolute; top: 0; bottom: 0;
  background: var(--accent); opacity: .35;
  pointer-events: none;
}
#code .ln.sel-full { position: relative; }
#code .ln.sel-full::before {
  content: ""; position: absolute; inset: 0 0 0 8px;
  background: var(--accent); opacity: .35; pointer-events: none;
}
/* de focus staat op #ime (een kind van #editor, niet van #code) zodra je in de editor zit
   -- #code:focus-within was daarom altijd onwaar en de selectie altijd "inactief" */
#editor:not(:focus-within) #code .sel,
#editor:not(:focus-within) #code .ln.sel-full::before { opacity: .18; }
/* geen browserselectie op de gutter of de code -- wij tekenen onze eigen laag */
#gutter, #code { user-select: none; -webkit-user-select: none; }

/* BRACKET-MATCH: een dunne rand om het haakje en zijn partner, geen re-render van de regel. */
#code .brk {
  position: absolute; top: 1px; bottom: 1px;
  outline: 1px solid var(--text-dim); outline-offset: -1px;
  pointer-events: none;
}
#code .brk-match { background: rgba(255,255,255,.08); }

/* de caret knippert op de compositor: 0 bytes over de lijn. Twee afwisselende
   animatienamen (blink-a / blink-b) i.p.v. "class weg, offsetWidth, class terug" --
   die truc forceert zelf een layout (zie e1a.js resetblink). .typing pauzeert de
   animatie tijdens/kort na een aanslag (S-0206: "stopt met knipperen tijdens typen"). */
#caret {
  position: absolute; width: 2px; height: var(--line-h);
  background: var(--text-strong);
  pointer-events: none; left: 0; top: 0;
}
#caret.blink-a { animation: blink 1.06s steps(1) infinite; }
#caret.blink-b { animation: blink2 1.06s steps(1) infinite; }
#caret.typing { animation: none; opacity: 1; }
@keyframes blink  { 0%,50% { opacity: 1; } 50.01%,100% { opacity: 0; } }
@keyframes blink2 { 0%,50% { opacity: 1; } 50.01%,100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { #caret.blink-a, #caret.blink-b { animation: none; } }

/* $ime: onzichtbaar, maar wel in de flow van tabtoetsen/focus -- geen display:none (dat
   breekt compositie in sommige browsers), wel buiten beeld. */
#ime {
  position: absolute; opacity: 0; pointer-events: none;
  width: 1px; height: 1px; left: 0; top: 0;
  resize: none; border: 0; padding: 0;
}
