import { useState, useEffect, useRef } from 'react'
import Icon from './components/Icon'
import {
  onMessage, notifyReady,
  requestMassstab, setMassstab,
  zoomExtents, zoomSelection, setShowLineweights,
  setMassstabDpi, detectMassstabDpi,
  setView, setDisplayMode,
  toggleOverrides, setOverridesPreset, openOverridesPanel,
  pickLayerCombination, saveLayerCombination,
  deleteLayerCombination, openLayerCombinationsDialog,
  openDossierSettings, openKameraPanel,
  setMasseActive, openMasseSettings,
  openAbout, createText, setTextSettings,
} from './lib/rhinoBridge'

const PRESETS = [
  { value: 1, label: '1:1' }, { value: 5, label: '1:5' },
  { value: 10, label: '1:10' }, { value: 20, label: '1:20' },
  { value: 25, label: '1:25' }, { value: 50, label: '1:50' },
  { value: 100, label: '1:100' }, { value: 200, label: '1:200' },
  { value: 500, label: '1:500' }, { value: 1000, label: '1:1000' },
]

// Reihe 1: 3D-Ansichten (Top, Iso, Persp) + Kamera-Button
// Reihe 2: 4 Gebaeudeansichten (Norden/Osten/Sueden/Westen) — Buchstaben
//          als Symbol, rotieren mit dossier_north_angle.
const VIEWS_ROW1 = [
  { value: 'Top',         icon: 'crop_landscape', kind: 'icon' },
  { value: 'Iso',         icon: 'view_in_ar',     kind: 'icon' },
  { value: 'Perspective', icon: '3d_rotation',    kind: 'icon' },
]
const VIEWS_ROW2 = [
  { value: 'N', label: 'N', kind: 'letter' },
  { value: 'O', label: 'O', kind: 'letter' },
  { value: 'S', label: 'S', kind: 'letter' },
  { value: 'W', label: 'W', kind: 'letter' },
]

function fmtScale(s) {
  if (s == null) return '—'
  if (s >= 1) return '1:' + (s >= 10 ? s.toFixed(0) : s.toFixed(1))
  return (1 / s).toFixed(2) + ':1'
}

function snapToPreset(s, tol = 0.03) {
  if (s == null) return null
  for (const p of PRESETS) {
    if (Math.abs(s - p.value) / p.value <= tol) return p.value
  }
  return null
}

function parseScale(input) {
  if (!input) return null
  const s = String(input).trim()
  for (const sep of [':', '=', '/']) {
    if (s.includes(sep)) {
      const [a, b] = s.split(sep, 2)
      const pa = parseFloat(a), pb = parseFloat(b)
      if (pa > 0 && pb > 0) return pb / pa
      return null
    }
  }
  const n = parseFloat(s)
  return n > 0 ? n : null
}

// ---------------------------------------------------------------------------
// Vectorworks-inspirierte Bar-Widgets: Icon links, Label/Select Mitte,
// Caret rechts — alle in einem rechteckigen Container, sichtbare Trennung
// zwischen Icon-Kompartiment und Inhalt.

const PILL_H = 20  // alte Pill-Hoehe (Buttons/Chips die nicht migriert sind)
const BAR_H  = 22  // neue Widget-Hoehe (BarSelect, BarButton, BarGroup)

const sep = {
  width: 1, height: 20,
  background: 'var(--border)', flexShrink: 0,
  margin: '0 3px',
}
const groupLabel = {
  fontSize: 9, color: 'var(--text-muted)', textTransform: 'uppercase',
  letterSpacing: '0.08em', fontWeight: 600,
  alignSelf: 'center', whiteSpace: 'nowrap',
  padding: '0 4px',
}
const pillSelect = {
  height: PILL_H, lineHeight: PILL_H + 'px',
  padding: '0 20px 0 10px', boxSizing: 'border-box',
  fontSize: 10,
}

// BarCombo: dunklerer (bg-input) Pill-Container der select + optional gear
// als EINE nahtlose Box rendert. Icon roh links daneben (kein Container).
// iconClickable=true macht das Icon zum Toggle-Button (Overrides etc.).
// valueAccent=true faerbt den Select-Text accent (fuer Massstab "gesetzt").
function BarCombo({
  icon, iconActive, iconClickable, onIconClick, iconTitle,
  value, onChange, width, title, children, disabled,
  onGear, gearTitle, valueAccent,
}) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      opacity: disabled ? 0.5 : 1, flexShrink: 0,
    }}>
      {/* Icon links — fixe Breite fuer X-Axis-Alignment zwischen Reihen.
          Wenn icon=null/undefined wird kein Icon-Slot reserviert. */}
      {icon && (iconClickable ? (
        <button onClick={onIconClick} title={iconTitle}
          style={{
            width: 18, height: BAR_H,
            background: 'transparent', border: 'none',
            cursor: 'pointer', flexShrink: 0, padding: 0,
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          }}>
          <Icon name={icon} size={13}
                style={{ color: iconActive ? 'var(--accent)' : 'var(--text-muted)' }} />
        </button>
      ) : (
        <span style={{
          width: 18, height: BAR_H, flexShrink: 0,
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Icon name={icon} size={13} style={{ color: 'var(--text-muted)' }} />
        </span>
      ))}
      {/* Combined pill: select + optional gear, gemeinsamer bg + border */}
      <div title={title}
        onMouseEnter={(e) => {
          if (disabled) return
          e.currentTarget.style.borderColor = 'var(--accent)'
          e.currentTarget.style.background = 'var(--bg-item-hover)'
        }}
        onMouseLeave={(e) => {
          e.currentTarget.style.borderColor = 'var(--border)'
          e.currentTarget.style.background = 'var(--bg-input)'
        }}
        style={{
          display: 'inline-flex', alignItems: 'stretch',
          height: BAR_H + 2, width, boxSizing: 'border-box',
          background: 'var(--bg-input)',
          border: '1px solid var(--border)',
          borderRadius: 999,
          overflow: 'hidden',
          transition: 'border-color 0.15s, background 0.15s',
        }}>
        <select
          value={value || ''}
          disabled={disabled}
          onChange={(e) => onChange(e.target.value)}
          style={{
            flex: 1, minWidth: 0,
            background: 'transparent',
            color: valueAccent ? 'var(--accent-light)' : 'var(--text-primary)',
            border: 'none', outline: 'none',
            padding: '0 22px 0 12px',
            fontSize: 11, fontFamily: 'var(--font)',
            fontWeight: valueAccent ? 600 : 500,
            appearance: 'none', WebkitAppearance: 'none',
            backgroundImage: 'var(--select-arrow)',
            backgroundRepeat: 'no-repeat',
            // Caret-Position differenziert: ohne Gear normaler Abstand
            // (10px vom Pill-Rand), mit Gear minimaler Abstand damit
            // er an den Gear ranruckt.
            backgroundPosition: onGear ? 'right 1px center' : 'right 10px center',
            cursor: disabled ? 'not-allowed' : 'pointer',
            letterSpacing: 0,
          }}
        >{children}</select>
        {onGear && (
          <button onClick={onGear} title={gearTitle}
            style={{
              background: 'transparent', border: 'none',
              padding: '0 8px', cursor: 'pointer',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              flexShrink: 0,
            }}>
            <Icon name="settings" size={12}
                  style={{ color: 'var(--text-muted)' }} />
          </button>
        )}
      </div>
    </div>
  )
}

// BarButton: pill-foermiger Icon-Button im selben Stil wie BarSelect.
// joinedLeft = linke Kante flach (dockt rechts an einen BarSelect-joinedRight).
function BarButton({ icon, onClick, title, disabled, active, joinedLeft }) {
  return (
    <button onClick={onClick} disabled={disabled} title={title}
      onMouseEnter={(e) => {
        if (disabled || active) return
        e.currentTarget.style.borderColor = 'var(--accent)'
        e.currentTarget.style.background = 'var(--bg-item-hover)'
      }}
      onMouseLeave={(e) => {
        if (active) return
        e.currentTarget.style.borderColor = 'var(--border)'
        e.currentTarget.style.background = 'var(--bg-input)'
      }}
      style={{
        height: BAR_H, width: BAR_H,
        background: active ? 'var(--accent)' : 'var(--bg-input)',
        border: '1px solid var(--border)',
        borderTopLeftRadius: joinedLeft ? 0 : 999,
        borderBottomLeftRadius: joinedLeft ? 0 : 999,
        borderTopRightRadius: 999, borderBottomRightRadius: 999,
        borderLeft: joinedLeft ? 'none' : '1px solid var(--border)',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        cursor: disabled ? 'not-allowed' : 'pointer',
        opacity: disabled ? 0.5 : 1, flexShrink: 0,
        padding: 0,
        transition: 'border-color 0.15s, background 0.15s',
      }}>
      <Icon name={icon} size={13}
            style={{ color: active ? 'var(--bg-panel)' : 'var(--text-muted)' }} />
    </button>
  )
}
const pillInput = {
  height: PILL_H, lineHeight: PILL_H + 'px',
  padding: '0 8px', boxSizing: 'border-box',
  borderRadius: 999,
  fontSize: 10,
}
const pillChip = {
  height: PILL_H, lineHeight: PILL_H + 'px',
  padding: '0 8px', boxSizing: 'border-box',
  display: 'inline-flex', alignItems: 'center',
  fontSize: 9,
}
const pillIconBtn = {
  width: PILL_H, height: PILL_H,
  borderRadius: '50%', boxSizing: 'border-box',
}

// Tonal button helper (filled when active, outlined when not)
function ToolButton({ active, onClick, icon, label, title, disabled }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={active ? 'btn-contained' : 'btn-outlined'}
      style={{ height: PILL_H, padding: '0 8px', boxSizing: 'border-box',
               fontSize: 9,
               opacity: disabled ? 0.4 : 1,
               cursor: disabled ? 'not-allowed' : 'pointer' }}
      title={title}
    >
      {icon && <Icon name={icon} size={12} />}
      {label && <span style={{ fontSize: 9 }}>{label}</span>}
    </button>
  )
}

// ---------------------------------------------------------------------------

export default function OberleisteApp() {
  const [state, setState] = useState({
    viewName: null, parallel: false, scale: null,
    pixelWidth: null, pixelHeight: null, unitSystem: '?',
    dpi: 96, dpiSource: 'default',
    showLineweights: false,
    viewMode: null, displayMode: null, displayModes: [],
    ortho: false, gridSnap: false, osnap: false,
    overridesEnabled: false, overridesCount: 0,
    cmdPrompt: '', cmdOptions: [],
    overridesActivePreset: null, overridesPresets: [],
    layerCombinations: [], layerCombinationActive: null,
    massePresets: [], masseActiveId: null,
    textSettings: { font: 'Helvetica', size: 0.20, bold: false, italic: false },
    textFonts: [],
    northAngle: 0,
    lastSetView: null,
  })
  const [appliedScale, setAppliedScale] = useState(null)
  const appliedScaleRef = useRef(null)
  const [draft, setDraft] = useState('')
  const [customMode, setCustomMode] = useState(false)  // Dropdown -> Custom-Input switch
  const customInputRef = useRef(null)

  useEffect(() => {
    onMessage('STATE', (s) => {
      setState((prev) => ({ ...prev, ...s }))
      // Dropdown spiegelt EXAKT den Backend-appliedScale fuer den aktuellen
      // Viewport. Kein Live-Skala-Fallback — das Dropdown ist statisch und
      // pro Viewport gebunden. Backend gibt null zurueck wenn der aktive
      // Viewport noch keinen gesetzten Massstab hat → Dropdown zeigt "1:?".
      const next = (typeof s?.appliedScale === 'number' && s.appliedScale > 0)
        ? s.appliedScale
        : null
      if (next !== appliedScaleRef.current) {
        setAppliedScale(next)
        appliedScaleRef.current = next
      }
    })
    notifyReady()
    setTimeout(() => requestMassstab(), 50)
  }, [])

  const isPerspective = state.parallel === false
  const scaleVal = state.scale
  const dropdownValue = appliedScale != null ? String(appliedScale) : '__none__'

  const applyDropdown = (val) => {
    if (val === '__none__') return
    if (val === '__custom__') {
      setDraft(appliedScale ? `1:${appliedScale}` : '')
      setCustomMode(true)
      // Nach dem Render: Focus + Selektion fuer schnelles Eintippen.
      setTimeout(() => {
        customInputRef.current?.focus()
        customInputRef.current?.select()
      }, 0)
      return
    }
    const r = parseFloat(val)
    if (r > 0) { setAppliedScale(r); appliedScaleRef.current = r; setMassstab(r) }
  }
  const applyDraft = () => {
    const r = parseScale(draft)
    if (r != null) {
      setAppliedScale(r); appliedScaleRef.current = r; setMassstab(r)
    }
    setDraft('')
    setCustomMode(false)
  }
  const cancelDraft = () => { setDraft(''); setCustomMode(false) }
  const apply100 = () => {
    if (appliedScale && appliedScale > 0) setMassstab(appliedScale)
  }

  // Active-Highlight aus lastSetView (vom Backend getrackt — vermeidet
  // Race-Conditions zwischen ChangeProjection und Viewport-State-Lesen).
  // Fallback wenn noch nie geklickt: Viewport-State raten.
  const matchView = (v) => {
    if (state.lastSetView) return state.lastSetView === v
    const name = (state.viewName || '').toLowerCase()
    if (v === 'Top') return name === 'top'
    if (v === 'Perspective') return state.parallel === false
    if (v === 'Iso') {
      const ortho = ['top', 'front', 'right', 'bottom', 'left', 'back']
      return state.parallel === true && !ortho.includes(name)
    }
    return false
  }

  // (Command-Bar wurde entfernt — Rhinos eigene Command-Line wird benutzt.)

  return (
    <div style={{
      width: '100%', height: '100%',
      display: 'flex', flexDirection: 'column',
      fontFamily: 'var(--font)', color: 'var(--text-primary)',
      background: 'var(--bg-panel)',
      borderBottom: '1px solid var(--border)',
      boxSizing: 'border-box',
      overflow: 'hidden',
    }}>
    {/* === Toolbar (View, Display, Massstab, Snap, Overrides) === */}
    <div style={{
      display: 'flex', alignItems: 'center', gap: 6,
      padding: '3px 10px 6px',
      overflowX: 'auto', overflowY: 'hidden',
      flexShrink: 0,
    }}>
      {/* Logo: DOSSIER. (Petrol-Punkt) — Klick = About-Fenster */}
      <button
        onClick={() => openAbout()}
        title="Über Dossier"
        style={{
          display: 'flex', alignItems: 'baseline', gap: 8,
          flexShrink: 0, userSelect: 'none',
          background: 'transparent', border: 'none', padding: 0,
          cursor: 'pointer', color: 'inherit',
        }}
      >
        <span style={{
          fontFamily: "Krungthep, 'Archivo Black', sans-serif",
          fontSize: 17,
          letterSpacing: '-0.02em',
          color: 'var(--text-primary)',
          lineHeight: 1,
        }}>
          DOSSIER<span style={{ color: 'var(--accent)' }}>.</span>
        </span>
      </button>
      <button
        onClick={() => openDossierSettings()}
        title="Dossier-Einstellungen"
        style={{
          background: 'transparent', border: 'none', padding: '2px 4px',
          cursor: 'pointer', color: 'var(--text-muted)',
          display: 'flex', alignItems: 'center', flexShrink: 0,
        }}
        onMouseEnter={(e) => e.currentTarget.style.color = 'var(--text-primary)'}
        onMouseLeave={(e) => e.currentTarget.style.color = 'var(--text-muted)'}
      >
        <Icon name="settings" size={14} />
      </button>
      <div style={sep} />
      {/* ====== VIEW 2x4 Grid ======
          Reihe 1: TOP / ISO / PERSP / 📷 (Kamera-Settings)
          Reihe 2: N / O / S / W (rotieren mit dossier_north_angle)
      */}
      {(() => {
        const VIEW_W = 140  // konsistent mit Massstab-Pills
        const CELL_W = Math.floor(VIEW_W / 4)
        const cellStyle = (isActive, isFirst) => ({
          height: BAR_H, minHeight: BAR_H, maxHeight: BAR_H,
          width: CELL_W,
          background: isActive ? 'var(--accent)' : 'var(--bg-input)',
          color: isActive ? 'var(--bg-panel)' : 'var(--text-primary)',
          border: 'none',
          borderLeft: isFirst ? 'none' : '1px solid var(--border)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          gap: 4, fontWeight: isActive ? 600 : 500,
          cursor: 'pointer', flexShrink: 0, padding: 0,
          appearance: 'none', WebkitAppearance: 'none',
          lineHeight: 1, boxSizing: 'border-box',
          transition: 'background 0.15s, color 0.15s',
        })
        const hoverIn = (isActive) => (e) => {
          if (isActive) return
          e.currentTarget.style.background = 'var(--bg-item-hover)'
          e.currentTarget.style.color = 'var(--accent-light)'
        }
        const hoverOut = (isActive) => (e) => {
          if (isActive) return
          e.currentTarget.style.background = 'var(--bg-input)'
          e.currentTarget.style.color = 'var(--text-primary)'
        }
        // Reihe 1: 3 View-Icons + Kamera-Settings
        const row1 = [
          ...VIEWS_ROW1,
          { value: '__camera__', icon: 'videocam', kind: 'icon' },
        ]
        return (
          <div style={{
            display: 'flex', flexDirection: 'column', gap: 4, flexShrink: 0,
          }}>
            {/* Reihe 1 */}
            <div style={{
              display: 'inline-flex', width: VIEW_W,
              height: BAR_H + 2, boxSizing: 'border-box',
              border: '1px solid var(--border)', borderRadius: 999,
              overflow: 'hidden', flexShrink: 0,
            }}>
              {row1.map((v, idx) => {
                const isActive = v.value !== '__camera__' && matchView(v.value)
                const label = v.value === '__camera__' ? 'Kamera-Einstellungen'
                  : `Ansicht ${v.value}`
                return (
                  <button key={v.value}
                    onClick={() => v.value === '__camera__'
                      ? openKameraPanel() : setView(v.value)}
                    title={label}
                    onMouseEnter={hoverIn(isActive)}
                    onMouseLeave={hoverOut(isActive)}
                    style={cellStyle(isActive, idx === 0)}>
                    <Icon name={v.icon} size={11} />
                  </button>
                )
              })}
            </div>
            {/* Reihe 2: N/O/S/W als Buchstaben */}
            <div style={{
              display: 'inline-flex', width: VIEW_W,
              height: BAR_H + 2, boxSizing: 'border-box',
              border: '1px solid var(--border)', borderRadius: 999,
              overflow: 'hidden', flexShrink: 0,
            }}>
              {VIEWS_ROW2.map((v, idx) => {
                const isActive = matchView(v.value)
                return (
                  <button key={v.value}
                    onClick={() => setView(v.value)}
                    title={`Ansicht aus ${v.value} (Norden = ${(state.northAngle || 0).toFixed(0)}°)`}
                    onMouseEnter={hoverIn(isActive)}
                    onMouseLeave={hoverOut(isActive)}
                    style={cellStyle(isActive, idx === 0)}>
                    <span style={{
                      fontFamily: 'DM Mono, monospace', fontSize: 10, fontWeight: 600,
                    }}>{v.label}</span>
                  </button>
                )
              })}
            </div>
          </div>
        )
      })()}

      <div style={sep} />

      {/* ====== 2-Reihen Preset-Block ======
          Oben: Display | Kombi
          Unten: Overrides | Masse
          Gleiche Pill-Breiten, identische X-Positionen (Grid-Layout). */}
      {(() => {
        const PRESET_W = 150
        return (
          <div style={{
            display: 'grid', gridTemplateColumns: 'auto auto',
            gap: '4px 6px', flexShrink: 0,
          }}>
            {/* Reihe 1, Spalte 1: Display */}
            <BarCombo
              icon="lightbulb"
              value={state.displayMode || ''}
              onChange={(v) => setDisplayMode(v)}
              title="Display-Mode (Wireframe / Shaded / Rendered / etc.)"
              width={PRESET_W}
            >
              {!state.displayMode && <option value="">—</option>}
              {(state.displayModes || []).map(dm => (
                <option key={dm.id} value={dm.name}>{dm.name}</option>
              ))}
            </BarCombo>
            {/* Reihe 1, Spalte 2: Ebenenkombination */}
            <BarCombo
              icon="layers"
              value={state.layerCombinationActive || '__none__'}
              onChange={(v) => {
                if (v === '__configure__') { openLayerCombinationsDialog(); return }
                if (v === '__save__') {
                  const suggested = state.layerCombinationActive
                    || `Kombi ${(state.layerCombinations || []).length + 1}`
                  const name = (window.prompt('Name für Ebenenkombination:', suggested) || '').trim()
                  if (!name) return
                  if ((state.layerCombinations || []).includes(name) &&
                      !window.confirm(`"${name}" überschreiben?`)) return
                  saveLayerCombination(name)
                  return
                }
                if (v === '__delete__') {
                  if (state.layerCombinationActive &&
                      window.confirm(`Kombination "${state.layerCombinationActive}" löschen?`))
                    deleteLayerCombination(state.layerCombinationActive)
                  return
                }
                pickLayerCombination(v === '__none__' ? null : v)
              }}
              title={state.layerCombinationActive
                ? `Aktive Kombi: ${state.layerCombinationActive}`
                : 'Keine Kombination — manuelle Sichtbarkeit'}
              width={PRESET_W}
              onGear={openLayerCombinationsDialog}
              gearTitle="Ebenenkombinationen bearbeiten"
            >
              <option value="__none__">— Eigene —</option>
              {(state.layerCombinations || []).map(name => (
                <option key={name} value={name}>{name}</option>
              ))}
              <option disabled>──────────</option>
              <option value="__save__">+ Aktuelle speichern…</option>
              {state.layerCombinationActive && (
                <option value="__delete__">🗑 Aktuelle löschen</option>
              )}
              <option value="__configure__">Bearbeiten…</option>
            </BarCombo>
            {/* Reihe 2, Spalte 1: Overrides (Toggle als Icon links) */}
            <BarCombo
              icon="auto_fix_high"
              iconClickable
              iconActive={state.overridesEnabled}
              onIconClick={() => toggleOverrides(!state.overridesEnabled)}
              iconTitle={state.overridesEnabled
                ? 'Grafische Overrides aktiv — klick zum Ausschalten'
                : 'Grafische Overrides ausgeschaltet'}
              value={state.overridesActivePreset || '__none__'}
              onChange={(v) => {
                if (v === '__configure__') { openOverridesPanel(); return }
                setOverridesPreset(v === '__none__' ? null : v)
              }}
              title={state.overridesActivePreset
                ? `Aktives Preset: ${state.overridesActivePreset} (${state.overridesCount} Regeln)`
                : `Kein Preset aktiv (${state.overridesCount} Regeln, frei editiert)`}
              width={PRESET_W}
              onGear={openOverridesPanel}
              gearTitle="Overrides-Regel-Editor öffnen"
            >
              <option value="__none__">{state.overridesCount > 0 ? `— (${state.overridesCount} Regeln)` : '—'}</option>
              {(state.overridesPresets || []).map(name => (
                <option key={name} value={name}>{name}</option>
              ))}
              <option disabled>──────────</option>
              <option value="__configure__">Konfigurieren…</option>
            </BarCombo>
            {/* Reihe 2, Spalte 2: Masse */}
            <BarCombo
              icon="straighten"
              value={state.masseActiveId || ''}
              onChange={(v) => setMasseActive(v)}
              title="Aktives Mass — Raum-Rundung + Mass-Linien-Format"
              width={PRESET_W}
              onGear={openMasseSettings}
              gearTitle="Masse bearbeiten / neues anlegen"
            >
              {(state.massePresets || []).length === 0 && <option value="">—</option>}
              {(state.massePresets || []).map(p => (
                <option key={p.id} value={p.id}>{p.name}</option>
              ))}
            </BarCombo>
          </div>
        )
      })()}

      <div style={sep} />

      {/* ====== MASSSTAB 2x2 ======
          Reihe 1: [Aktueller Massstab]    [Massstab-Dropdown (gruen wenn gesetzt)]
          Reihe 2: [Zoom-Verhaeltnis %]    [Buttons]
      */}
      {(() => {
        // Buttons-Pill: gleiche Logik wie View-Toggle (weiss default,
        // grün on hover, accent-fill wenn active)
        const PILL_W = 140  // Gleiche Breite fuer Dropdown + Buttons-Pill
        const N_BTN = 4
        const BTN_W = Math.floor(PILL_W / N_BTN)  // jeder Button gleich breit
        const SegBtn = ({ icon, onClick, title, disabled, active, isFirst, isLast }) => (
          <button onClick={onClick} disabled={disabled} title={title}
            onMouseEnter={(e) => {
              if (disabled || active) return
              e.currentTarget.style.background = 'var(--bg-item-hover)'
              e.currentTarget.style.color = 'var(--accent-light)'
            }}
            onMouseLeave={(e) => {
              if (active) return
              e.currentTarget.style.background = 'var(--bg-input)'
              e.currentTarget.style.color = 'var(--text-primary)'
            }}
            style={{
              height: BAR_H, minHeight: BAR_H, maxHeight: BAR_H,
              width: BTN_W,
              background: active ? 'var(--accent)' : 'var(--bg-input)',
              color: active ? 'var(--bg-panel)' : 'var(--text-primary)',
              border: 'none',
              borderLeft: isFirst ? 'none' : '1px solid var(--border)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              cursor: disabled ? 'not-allowed' : 'pointer',
              opacity: disabled ? 0.4 : 1, flexShrink: 0,
              padding: 0,
              appearance: 'none', WebkitAppearance: 'none',
              lineHeight: 1, boxSizing: 'border-box',
              transition: 'background 0.15s, color 0.15s',
            }}>
            <Icon name={icon} size={11} />
          </button>
        )
        const ratio = (!isPerspective && appliedScale && scaleVal)
          ? appliedScale / scaleVal
          : null
        const ratioText = ratio == null
          ? '—'
          : ratio >= 1
            ? Math.round(ratio * 100) + '%'
            : (ratio * 100).toFixed(ratio < 0.1 ? 1 : 0) + '%'
        const atScale = ratio != null && Math.abs(ratio - 1) < 0.005
        const STAT_W = 70   // Breite der gemeinsamen Stat-Box
        // Gesamte 2-Reihen-Hoehe: 2 × BAR_H + gap (4px) = ~48px
        return (
      <div style={{
        display: 'grid', gridTemplateColumns: 'auto auto', gap: '4px 6px',
        alignItems: 'center', flexShrink: 0,
      }}>
        {/* Spalte 1, beide Reihen: EINE Pill mit Live-Massstab oben und
            Zoom-% unten. Text-Hoehen bleiben identisch zu den
            urspruenglichen 2 Chips — der Trennstrich sitzt in der Mitte
            des 4px-Gaps zwischen ihnen. */}
        <div style={{
          gridRow: '1 / span 2',
          display: 'flex', flexDirection: 'column',
          width: STAT_W, height: BAR_H * 2 + 6,
          background: atScale ? 'var(--accent-dim)' : 'var(--bg-input)',
          color: atScale ? 'var(--accent-light)' : 'var(--text-primary)',
          border: '1px solid ' + (atScale ? 'var(--accent)' : 'var(--border)'),
          borderRadius: 14,
          overflow: 'hidden',
          fontFamily: 'DM Mono, monospace', fontSize: 11,
          fontWeight: atScale ? 600 : 500,
          flexShrink: 0,
          transition: 'border-color 0.15s, background 0.15s',
        }}>
          <div style={{
            height: BAR_H,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }} title={isPerspective ? 'Perspektive — kein Massstab' : 'Aktueller Live-Massstab'}>
            {isPerspective ? '—' : fmtScale(scaleVal)}
          </div>
          <div style={{ height: 6, position: 'relative' }}>
            <div style={{
              position: 'absolute', left: 6, right: 6,
              top: '50%', height: 1,
              background: 'var(--border)',
            }} />
          </div>
          <div style={{
            height: BAR_H,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }} title={ratio != null
            ? `Aktueller Zoom = ${ratioText} des gesetzten Massstabs`
            : (isPerspective ? 'Perspektive' : 'Kein Massstab gesetzt')}>
            {ratioText}
          </div>
        </div>
        {/* Reihe 1, Spalte 2: Gesetzter Massstab Dropdown — KEIN Icon, gleiche
            Breite wie Buttons-Pill darunter, exakt uebereinander */}
        {customMode ? (
          <input
            ref={customInputRef}
            disabled={isPerspective}
            type="text" placeholder="1:N"
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') applyDraft()
              else if (e.key === 'Escape') cancelDraft()
            }}
            onBlur={applyDraft}
            style={{
              height: BAR_H, width: PILL_W,
              background: 'var(--bg-input)',
              color: 'var(--text-primary)',
              border: '1px solid var(--border)',
              borderRadius: 999,
              padding: '0 12px', fontSize: 11,
              fontFamily: 'DM Mono, monospace',
              outline: 'none',
            }}
            title="Massstab eingeben (Enter = uebernehmen, Esc = abbrechen)"
          />
        ) : (
          <BarCombo
            value={dropdownValue}
            onChange={(v) => applyDropdown(v)}
            disabled={isPerspective}
            width={PILL_W}
            title="Gesetzter Massstab"
          >
            <option value="__none__">—</option>
            {PRESETS.map(p => (
              <option key={p.value} value={String(p.value)}>{p.label}</option>
            ))}
            {appliedScale != null && !PRESETS.some(p => p.value === appliedScale) && (
              <option value={String(appliedScale)}>1:{appliedScale}</option>
            )}
            <option value="__custom__">Eigener…</option>
          </BarCombo>
        )}
        {/* Reihe 2, Spalte 2: Buttons-Pill — gleiche Breite wie Dropdown */}
        <div style={{
          display: 'inline-flex', width: PILL_W,
          height: BAR_H + 2, boxSizing: 'border-box',
          border: '1px solid var(--border)', borderRadius: 999,
          overflow: 'hidden', flexShrink: 0, justifySelf: 'start',
        }}>
          <SegBtn icon="percent" onClick={apply100} isFirst
                  disabled={isPerspective || !appliedScale}
                  title={appliedScale ? `Zoom auf 1:${appliedScale} snappen` : 'Erst einen Massstab wählen'} />
          <SegBtn icon="fit_screen" onClick={zoomExtents}
                  title="Auf gesamten Inhalt zoomen" />
          <SegBtn icon="center_focus_strong" onClick={zoomSelection}
                  title="Auf Selektion zoomen" />
          <SegBtn
            icon={state.showLineweights ? 'print' : 'edit'}
            active={state.showLineweights}
            onClick={() => setShowLineweights(!state.showLineweights)}
            isLast
            title={state.showLineweights
              ? 'Print-View aktiv — klick zum Ausschalten'
              : 'Strichstärken anzeigen (Print-View)'} />
        </div>
      </div>
        )
      })()}

      <div style={sep} />

      {/* ====== TEXT-Block 2-Reihen ======
          Reihe 1: Font-Dropdown + Groesse (mm)
          Reihe 2: B/I-Toggles + "Text einfuegen"-Button
      */}
      {(() => {
        const ts = state.textSettings || {}
        const fonts = state.textFonts || []
        const updateTs = (patch) => setTextSettings({ ...ts, ...patch })
        const TEXT_W = 150
        return (
          <div style={{
            display: 'grid', gridTemplateColumns: 'auto auto', gap: '4px 6px',
            alignItems: 'center', flexShrink: 0,
          }}>
            {/* Reihe 1, Spalte 1: Font-Dropdown */}
            <BarCombo
              icon="text_fields"
              value={ts.font || ''}
              onChange={(v) => updateTs({ font: v })}
              width={TEXT_W}
              title="Schriftart"
            >
              {fonts.length === 0 && <option value="">—</option>}
              {fonts.map(f => <option key={f} value={f}>{f}</option>)}
            </BarCombo>
            {/* Reihe 1, Spalte 2: Groesse (mm) */}
            <div style={{
              display: 'inline-flex', alignItems: 'center', gap: 4,
              height: BAR_H, padding: '0 10px',
              background: 'var(--bg-input)',
              border: '1px solid var(--border)',
              borderRadius: 999,
              flexShrink: 0, width: 90,
            }}>
              <input
                type="number" step="0.01" min="0.01"
                value={ts.size != null ? ts.size : 0.2}
                onChange={(e) => {
                  const v = parseFloat(e.target.value)
                  if (!isNaN(v) && v > 0) updateTs({ size: v })
                }}
                style={{
                  flex: 1, minWidth: 0,
                  background: 'transparent', border: 'none', outline: 'none',
                  color: 'var(--text-primary)',
                  fontSize: 11, fontFamily: 'DM Mono, monospace',
                  padding: 0, textAlign: 'right',
                  appearance: 'auto',
                }}
                title="Texthoehe in Model-Units"
              />
              <span style={{ fontSize: 9, color: 'var(--text-muted)' }}>m</span>
            </div>
            {/* Reihe 2, Spalte 1: B/I-Toggles */}
            <div style={{
              display: 'inline-flex',
              border: '1px solid var(--border)', borderRadius: 999,
              overflow: 'hidden', flexShrink: 0, width: TEXT_W,
            }}>
              <button
                onClick={() => updateTs({ bold: !ts.bold })}
                onMouseEnter={(e) => {
                  if (ts.bold) return
                  e.currentTarget.style.background = 'var(--bg-item-hover)'
                  e.currentTarget.style.color = 'var(--accent-light)'
                }}
                onMouseLeave={(e) => {
                  if (ts.bold) return
                  e.currentTarget.style.background = 'var(--bg-input)'
                  e.currentTarget.style.color = 'var(--text-primary)'
                }}
                style={{
                  flex: 1, height: BAR_H,
                  background: ts.bold ? 'var(--accent)' : 'var(--bg-input)',
                  color: ts.bold ? 'var(--bg-panel)' : 'var(--text-primary)',
                  border: 'none', cursor: 'pointer',
                  fontWeight: 700, fontSize: 11,
                  transition: 'background 0.15s, color 0.15s',
                }}
                title="Fett"
              >B</button>
              <button
                onClick={() => updateTs({ italic: !ts.italic })}
                onMouseEnter={(e) => {
                  if (ts.italic) return
                  e.currentTarget.style.background = 'var(--bg-item-hover)'
                  e.currentTarget.style.color = 'var(--accent-light)'
                }}
                onMouseLeave={(e) => {
                  if (ts.italic) return
                  e.currentTarget.style.background = 'var(--bg-input)'
                  e.currentTarget.style.color = 'var(--text-primary)'
                }}
                style={{
                  flex: 1, height: BAR_H,
                  background: ts.italic ? 'var(--accent)' : 'var(--bg-input)',
                  color: ts.italic ? 'var(--bg-panel)' : 'var(--text-primary)',
                  border: 'none', borderLeft: '1px solid var(--border)',
                  cursor: 'pointer',
                  fontStyle: 'italic', fontSize: 11,
                  transition: 'background 0.15s, color 0.15s',
                }}
                title="Kursiv"
              >I</button>
            </div>
            {/* Reihe 2, Spalte 2: "Text einfuegen" Button */}
            <button
              onClick={() => createText()}
              onMouseEnter={(e) => {
                e.currentTarget.style.background = 'var(--bg-item-hover)'
                e.currentTarget.style.borderColor = 'var(--accent)'
                e.currentTarget.style.color = 'var(--accent-light)'
              }}
              onMouseLeave={(e) => {
                e.currentTarget.style.background = 'var(--bg-input)'
                e.currentTarget.style.borderColor = 'var(--border)'
                e.currentTarget.style.color = 'var(--text-primary)'
              }}
              style={{
                width: 90, height: BAR_H,
                background: 'var(--bg-input)',
                color: 'var(--text-primary)',
                border: '1px solid var(--border)',
                borderRadius: 999,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                gap: 4, cursor: 'pointer',
                fontSize: 11, fontWeight: 500,
                transition: 'background 0.15s, color 0.15s, border-color 0.15s',
              }}
              title="Position picken → Text tippen → Enter"
            >
              <Icon name="add" size={12} />
              Text
            </button>
          </div>
        )
      })()}

      {/* Snap-Toggles (Ortho/Grid/OSnap) sind in Rhinos eigener Footer-Bar
          schon vorhanden — hier rausgenommen um Doppelung zu vermeiden. */}

      {/* Spacer am rechten Rand */}
      <div style={{ flex: 1 }} />
    </div>
    </div>
  )
}
