/* Editor-chrome (sectie H, DSC-096 t/m DSC-113).
 *
 * De dunne bewerklaag óver de identiek-aan-live gerenderde widgets: frame-
 * omlijningen, zwevende toolbar, breedte-handvatten en preset-preview.
 * Descendant-selectors op een toestandsklasse (.is-selected) kunnen niet met
 * utilities in de ERB; alles op tokens. Het echte editor-gedrag (SortableJS,
 * autosave) komt in spoor C — deze laag is puur visueel. */

/* DSC-096 — widget-frame: rust zonder omlijning, subtiel bij hover, sterk bij
 * selectie. De omlijning staat lós van het widget (outline + offset) zodat de
 * live-rendering pixelidentiek blijft. .is-hover bestaat om de hover-staat
 * statisch te tonen op /design. */
.ds-widget-frame {
  position: relative;
  border-radius: var(--radius-lg);
  outline: 2px solid transparent;
  outline-offset: 6px;
  transition: outline-color var(--duration-fast) ease;
}
.ds-widget-frame:hover,
.ds-widget-frame.is-hover {
  outline-color: color-mix(in srgb, var(--color-brand) 40%, transparent);
}
.ds-widget-frame.is-selected {
  outline-color: var(--color-brand);
}
/* Slepend (DSC-098): ghost-verschijning met raised-schaduw, licht gekanteld. */
.ds-widget-frame.is-dragging {
  cursor: grabbing;
  outline-color: var(--color-brand);
  box-shadow: var(--shadow-raised);
  transform: rotate(1deg);
  background: white;
}

/* R3-9 — leeg widget: een widget dat niets rendert (onvolledig ingesteld:
 * afbeelding zonder beeld, video zonder youtube_id, iframe zonder url) klapt op
 * het canvas tot 0px hoog in en wordt zo onzichtbaar en onselecteerbaar. Alleen
 * op het editor-canvas (pages/editor/_widget_frame) krijgt zo'n frame een
 * gestippelde omranding met muted vlak en een minimumhoogte, zodat het zichtbaar
 * blijft en de placeholder erin past. De live-weergave rendert het widget nog
 * steeds helemaal niet (PAG-124). */
.ds-widget-frame[data-widget-empty] {
  min-height: 84px;
  border: 1px dashed var(--color-line);
  background: color-mix(in srgb, var(--color-offwhite) 55%, transparent);
}
.ds-widget-empty {
  display: flex;
  min-height: 84px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 12px 16px;
  text-align: center;
}
.ds-widget-empty-icoon {
  margin-bottom: 2px;
  color: var(--color-subtle);
}
.ds-widget-empty-titel {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--color-black);
}
.ds-widget-empty-tekst {
  font-size: 0.8125rem;
  color: var(--color-subtle);
}

/* Zwevende toolbar bóven het geselecteerde frame (verschijnt in 220ms). */
.ds-widget-toolbar {
  position: absolute;
  top: -6px;
  right: -6px;
  transform: translateY(-100%);
  /* Boven de sectie-add-zones en sectie-controls (z-20), anders vangen die de
   * klikken op de kleine toolbar-knopjes bij de sectiegrens (feedback Lennart). */
  z-index: 25;
  display: none;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--color-line);
  border-radius: 9999px;
  background: white;
  box-shadow: var(--shadow-raised);
}
.ds-widget-frame.is-selected > .ds-widget-toolbar {
  display: flex;
  animation: ds-enter-up var(--duration-base) var(--ease-out-soft) backwards;
}
/* FEEDBACK jul 2026 (Lennart): de toolbar mag nooit uit beeld scrollen zolang
 * het widget geselecteerd is. widget_toolbar_controller#klemToolbar klemt de
 * natuurlijke plek (rechtsboven het frame) tussen de onderkant van de sticky
 * editor-chrome en de onderrand van de viewport; daarbuiten pint hij de toolbar
 * met deze klasse vast (top/right komen inline uit de meting). De wissel
 * gebeurt exact op de grens, dus zonder visuele sprong. transform vervalt: de
 * -100%-lift zit al in de berekende top. z-index blijft 25 — lager dan de
 * sticky chrome (z-30), dus in het ergste geval schuift hij er één frame
 * ondergedoken achter i.p.v. eroverheen. */
.ds-widget-toolbar.is-pinned {
  position: fixed;
  transform: none;
}
.ds-widget-toolbar-grip {
  cursor: grab;
}
.ds-widget-toolbar-grip:active {
  cursor: grabbing;
}

/* FEEDBACK ronde 4 (R4-14): breedte × hoogte-dropdowns in de zwevende toolbar.
 * Compacte selects (het aantal kolommen resp. rij-eenheden); een type met een
 * vaste maat toont in plaats daarvan een niet-interactief cijfer. */
.ds-widget-toolbar-select {
  height: 28px;
  padding: 0 4px;
  border: 1px solid var(--color-line);
  border-radius: 6px;
  background: white;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--color-black);
  cursor: pointer;
  transition: border-color var(--duration-fast) ease;
}
.ds-widget-toolbar-select:hover {
  border-color: var(--color-brand);
}
.ds-widget-toolbar-select:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 1px;
}
.ds-widget-toolbar-vast {
  min-width: 18px;
  text-align: center;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--color-subtle);
}
/* FEEDBACK ronde 7 (R7-5): content-gedreven hoogte — greyed "auto" i.p.v. een
 * dropdown, want de auteur bepaalt de hoogte hier niet. */
.ds-widget-toolbar-auto {
  padding: 0 6px;
  font-size: 12px;
  font-style: italic;
  color: var(--color-subtle);
  cursor: default;
}

/* FEEDBACK ronde 4/5 (R4-13, R5-4): oplichtend doelvak tijdens het slepen; het
 * toont op welke gridcel de widget landt. De drop duwt overlappende widgets
 * opzij (naar beneden), dus het vak is altijd geldig. Alleen in het editor-grid. */
.ds-drop-cell {
  z-index: 5;
  border: 2px dashed var(--color-brand);
  border-radius: var(--radius-md, 8px);
  background: color-mix(in srgb, var(--color-brand) 12%, transparent);
  pointer-events: none;
}

/* FEEDBACK ronde 7 (R7-4): tijdens het slepen krijgen ALLE widgets op de pagina
 * een outline + subtiele oranje overlay, zodat je duidelijk ziet waar de blokken
 * staan en hoe groot ze zijn (de gridcel = het blok). De gesleepte widget zelf
 * (ghost) doet niet mee; die is al gedimd. */
.ds-sortable-dragging .ds-widget-frame {
  outline: 1px solid color-mix(in srgb, var(--color-brand) 45%, transparent);
  outline-offset: 0;
}
.ds-sortable-dragging .ds-widget-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 4;
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-brand) 8%, transparent);
  pointer-events: none;
}
.ds-sortable-dragging .ds-widget-frame.ds-sortable-ghost {
  outline-color: transparent;
}
.ds-sortable-dragging .ds-widget-frame.ds-sortable-ghost::after {
  display: none;
}

/* Snap-visualisatie bij het hoogte-handvat: tijdens het slepen licht het
 * 8px-radengrid op in het widgetvlak (pendant van de kolomoverlay). */
.ds-height-grid-overlay {
  pointer-events: none;
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: repeating-linear-gradient(
    to bottom,
    color-mix(in srgb, var(--color-brand) 35%, transparent) 0 1px,
    transparent 1px 8px
  );
}

/* DSC-100 — achtergrondpreset-kiezer: vijf ronde swatches; de gekozen preset
 * krijgt een duidelijke ring in Almost Black. */
.ds-preset-swatch {
  height: 28px;
  width: 28px;
  border: 1px solid var(--color-line);
  border-radius: 9999px;
  transition: transform var(--duration-fast) ease;
}
.ds-preset-swatch:hover {
  transform: scale(1.1);
}
.ds-preset-swatch[aria-pressed="true"] {
  outline: 2px solid var(--color-black);
  outline-offset: 2px;
}

/* Preset-preview in de demo: het sectievlak wisselt mee met de gekozen swatch;
 * de duotone-tekstkleur schakelt automatisch (op donker → Kinda White). */
.ds-preset-preview {
  transition: background-color var(--duration-base) ease;
}
.ds-preset-preview[data-preset="white"] {
  background: white;
  color: var(--color-black);
}
.ds-preset-preview[data-preset="offwhite"] {
  background: var(--color-offwhite);
  color: var(--color-black);
}
.ds-preset-preview[data-preset="brand"] {
  background: var(--color-brand);
  color: var(--color-black);
}
.ds-preset-preview[data-preset="ink"] {
  background: var(--color-black);
  color: var(--color-offwhite);
}
.ds-preset-preview[data-preset="image"] {
  background:
    linear-gradient(rgb(22 22 22 / 0.65), rgb(22 22 22 / 0.65)),
    linear-gradient(135deg, var(--color-brand) 0%, var(--color-black) 100%);
  color: var(--color-offwhite);
}

/* DSC-108 — Lucide-icoonkiezer: gekozen icoon krijgt een brand-ring. */
.ds-icon-choice[aria-pressed="true"] {
  outline: 2px solid var(--color-brand);
  outline-offset: 1px;
  background: var(--color-offwhite);
}

/* DSC-112 — hero-focuspunt-picker (Lennart #8, PAG-127): sleepbare indicator
 * over het coverbeeld. touch-action: none voorkomt dat de pagina meescrollt
 * tijdens het slepen op touch; de indicator zelf negeert pointer events zodat
 * de picker altijd het slepende element blijft, ook als je op de indicator
 * begint. */
.ds-hero-focus {
  cursor: grab;
  touch-action: none;
}
.ds-hero-focus:active {
  cursor: grabbing;
}
.ds-hero-focus-indicator {
  pointer-events: none;
}

/* FEEDBACK ronde 2 (R2-7): op het editor-canvas rendert de widget-inhoud
 * pixelidentiek aan live, inclusief eigen iframes (embed/video-facade), links en
 * knoppen. Een iframe is een eigen browsing context, dus een klik erin bereikt
 * page-editor#selectWidget nooit — het widget was daardoor niet te selecteren.
 * Maak de widget-inhoud transparant voor pointer events zodat ELKE klik door de
 * inhoud heen op het .ds-widget-frame landt (dat selecteert het widget). Dit
 * attribuut bestaat uitsluitend in de editor-render (pages/editor/_widget_frame),
 * dus de live-weergave blijft volledig interactief. */
[data-widget-editor-content] {
  pointer-events: none;
}

/* FEEDBACK ronde 4 (R4-8/R4-9) — widget-kiezer + '+ sectie'-grenszones.
 *
 * De overlay-knoppen '+ widget' (widget-kiezer) en '+ sectie' (grenszones)
 * liggen in de editor over de sectiegrenzen en botsten met de aangrenzende
 * chrome (het widget-grid, de sectie-controls, elkaars grenszone). Ze bestaan
 * uitsluitend in de editor-render (pages/editor/*), dus deze regels raken de
 * live-weergave niet. De zones zijn absoluut gepositioneerd: deze marges
 * verschuiven de zones zelf wél, maar reflowen de flow-inhoud niet — dus geen
 * layout-schokken. */

/* R4-8: til de '+ widget'-knop een paar px omhoog, weg van de '+ sectie'-grens
 * eronder en het grid, zodat de pill-knoppen elkaar niet meer raken. */
.ds-widget-picker {
  margin-bottom: 8px;
}

/* R4-9: de kiezer-container staat in ruststand op z-10 (onder de z-20 sectie-
 * controls en '+ sectie'-grenszones). Het paneel is wél hoger opgemaakt, maar
 * zat gevangen in de z-10 stacking-context van de container en verdween daardoor
 * achter de z-20 '+ sectie'-knop. Til de OPEN container boven de sectie-
 * controls/grenszones (20), zodat het geopende paneel bovenop ligt en niets
 * erdoorheen prikt. FEEDBACK jul 2026 (Lennart): 25, niet 30 — op 30 stond hij
 * gelijk aan de sticky editor-chrome en won hij op DOM-volgorde, waardoor het
 * paneel bij het scrollen óver de menubalk heen tekende. Onder de 30 schuift
 * hij er netjes onderdoor. */
.ds-widget-picker.is-open {
  z-index: 25;
}

/* R4-8: wat lucht rond de '+ sectie'-grenszones zodat de knop niet tegen de
 * sectie-controls (boven) of het widget-grid (onder) aan komt. */
.ds-section-add-zone--top {
  margin-top: -6px;
}
.ds-section-add-zone--bottom {
  margin-bottom: -6px;
}
