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,
} 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' },
]

const VIEWS = [
  { value: 'Top',         icon: 'view_quilt',     label: 'Top' },
  { value: 'Front',       icon: 'north',          label: 'Front' },
  { value: 'Right',       icon: 'east',           label: 'Right' },
  { value: 'Iso',         icon: 'view_in_ar',     label: 'Iso' },
  { value: 'Perspective', icon: '3d_rotation',    label: 'Persp' },
]

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,
}

// BarSelect: Icon roh links + custom-pill <select>. Vectorworks-Stil —
// dunkler Pill-Container, Caret rechts, joinedRight macht die rechte Kante
// flach fuer die Verkettung mit BarButton.
function BarSelect({ icon, value, onChange, title, disabled, width, children, joinedRight }) {
  return (
    <div title={title} style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      opacity: disabled ? 0.5 : 1, flexShrink: 0,
    }}>
      {icon && (
        <Icon name={icon} size={13}
              style={{ color: 'var(--text-muted)', flexShrink: 0 }} />
      )}
      <select
        value={value || ''}
        disabled={disabled}
        onChange={(e) => onChange(e.target.value)}
        style={{
          height: BAR_H, width,
          background: 'var(--bg-item)',
          color: 'var(--text-primary)',
          border: '1px solid var(--border)',
          borderTopLeftRadius: 999, borderBottomLeftRadius: 999,
          borderTopRightRadius: joinedRight ? 0 : 999,
          borderBottomRightRadius: joinedRight ? 0 : 999,
          borderRight: joinedRight ? 'none' : '1px solid var(--border)',
          padding: '0 24px 0 12px',
          fontSize: 11, fontFamily: 'var(--font)',
          appearance: 'none', WebkitAppearance: 'none',
          backgroundImage: 'var(--select-arrow)',
          backgroundRepeat: 'no-repeat',
          backgroundPosition: 'right 9px center',
          cursor: disabled ? 'not-allowed' : 'pointer',
          flexShrink: 0, outline: 'none',
          letterSpacing: 0,
        }}
      >{children}</select>
    </div>
  )
}

// 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 */}
      {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} style={{
        display: 'inline-flex', alignItems: 'stretch',
        height: BAR_H, width,
        background: 'var(--bg-input)',
        border: '1px solid var(--border)',
        borderRadius: 999,
        overflow: 'hidden',
      }}>
        <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 klebt am rechten Rand des Select-Bereichs (= direkt
            // links vom Gear). Mit Gear: symmetrische Abstaende
            // caret-to-gear ≈ gear-to-pill-right-edge.
            backgroundPosition: 'right 2px 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}
      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,
      }}>
      <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,
  })
  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)
  }

  // Aktuelles View-Match. Orthogonale Standard-Views matchen via viewName.
  // 'Iso' und 'Perspective' werden via parallel-Flag unterschieden — die
  // Rhino-Viewport-Namen sind beide oft "Perspective".
  const matchView = (v) => {
    const name = (state.viewName || '').toLowerCase()
    const ortho = ['top', 'front', 'right', 'bottom', 'left', 'back']
    if (v === 'Iso') {
      // Parallel-Projektion + kein orthogonaler Standardname → Iso
      return state.parallel === true && !ortho.includes(name)
    }
    if (v === 'Perspective') {
      return state.parallel === false
    }
    return name === v.toLowerCase()
  }

  // (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 (Top/Front/Right/Iso/Persp + Kamera) ======
          Segmented-Pill-Gruppe analog Vectorworks. Active = accent fill. */}
      <div style={{ display: 'inline-flex', flexShrink: 0 }}>
        {VIEWS.map((v, idx) => {
          const isFirst = idx === 0
          const isLast = idx === VIEWS.length - 1
          const isActive = matchView(v.value)
          return (
            <button
              key={v.value}
              onClick={() => setView(v.value)}
              title={`Ansicht ${v.label}`}
              style={{
                height: BAR_H, padding: '0 10px',
                background: isActive ? 'var(--accent)' : 'var(--bg-input)',
                color: isActive ? 'var(--bg-panel)' : 'var(--text-primary)',
                border: '1px solid var(--border)',
                borderLeft: isFirst ? '1px solid var(--border)' : 'none',
                borderTopLeftRadius: isFirst ? 999 : 0,
                borderBottomLeftRadius: isFirst ? 999 : 0,
                borderTopRightRadius: isLast ? 999 : 0,
                borderBottomRightRadius: isLast ? 999 : 0,
                display: 'inline-flex', alignItems: 'center', gap: 4,
                fontSize: 10, fontWeight: isActive ? 600 : 500,
                cursor: 'pointer', flexShrink: 0,
              }}
            >
              <Icon name={v.icon} size={13} />
              <span>{v.label}</span>
            </button>
          )
        })}
      </div>
      <BarButton icon="videocam" onClick={() => openKameraPanel()}
                  title="Kamera-Einstellungen (Position, Target, Linse, Presets)" />

      <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]
      */}
      {(() => {
        const SegBtn = ({ icon, onClick, title, disabled, active, isFirst, isLast }) => (
          <button onClick={onClick} disabled={disabled} title={title}
            style={{
              height: BAR_H, width: 30,
              background: active ? 'var(--accent)' : 'var(--bg-input)',
              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,
            }}>
            <Icon name={icon} size={13}
                  style={{ color: active ? 'var(--bg-panel)' : 'var(--text-muted)' }} />
          </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 = 80   // Breite der linken Stat-Chips (1:N / %)
        const statChipStyle = (accentTint) => ({
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          height: BAR_H, width: STAT_W,
          background: accentTint ? 'var(--accent-dim)' : 'var(--bg-input)',
          color: accentTint ? 'var(--accent-light)' : 'var(--text-muted)',
          border: '1px solid var(--border)',
          borderRadius: 999,
          fontFamily: 'DM Mono, monospace', fontSize: 11,
          fontWeight: accentTint ? 600 : 500,
          flexShrink: 0,
        })
        return (
      <div style={{
        display: 'grid', gridTemplateColumns: 'auto auto', gap: '4px 6px',
        alignItems: 'center', flexShrink: 0,
      }}>
        {/* Reihe 1, Spalte 1: Aktueller Live-Massstab */}
        <div style={statChipStyle(false)}
             title={isPerspective ? 'Perspektive — kein Massstab' : 'Aktueller Live-Massstab'}>
          {isPerspective ? '—' : fmtScale(scaleVal)}
        </div>
        {/* Reihe 1, Spalte 2: Gesetzter Massstab Dropdown */}
        {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: 158,
              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
            icon="straighten"
            value={dropdownValue}
            onChange={(v) => applyDropdown(v)}
            disabled={isPerspective}
            width={140}
            valueAccent={appliedScale != null}
            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 1: Zoom-Verhaeltnis zum gesetzten Massstab */}
        <div style={statChipStyle(atScale)}
             title={ratio != null
               ? `Aktueller Zoom = ${ratioText} des gesetzten Massstabs`
               : (isPerspective ? 'Perspektive' : 'Kein Massstab gesetzt')}>
          {ratioText}
        </div>
        {/* Reihe 2, Spalte 2: Buttons-Pill */}
        <div style={{
          display: 'inline-flex',
          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>
        )
      })()}

      {/* 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>
  )
}
