/* ========================================================================== Components — the things you click. Each rule owns one class. ========================================================================== */ /* --- File rail entry ------------------------------------------------------- An active file is marked by a rule at the left edge, the way an editor marks the current line — not by a filled pill. -------------------------------------------------------------------------- */ .file-selector { position: relative; display: block; padding: var(--dn-space-1) var(--dn-space-2) var(--dn-space-1) var(--dn-space-3); border-radius: var(--dn-radius-sm); color: var(--dn-fg-muted); font-family: var(--dn-font-code); font-size: var(--dn-text-sm); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color var(--dn-dur-fast) var(--dn-ease), background-color var(--dn-dur-fast) var(--dn-ease); } .file-selector::before { content: ""; position: absolute; inset-block: 3px; left: 0; width: 2px; border-radius: 999px; background: var(--dn-accent); transform: scaleY(0); transition: transform var(--dn-dur) var(--dn-ease); } .file-selector:hover { background: var(--dn-bg-raised); color: var(--dn-fg); } .file-selector.active { color: var(--dn-fg); background: var(--dn-bg-raised); } .file-selector.active::before { transform: scaleY(1); } /* --- Buttons ---------------------------------------------------------------- */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--dn-space-2); padding: var(--dn-space-2) var(--dn-space-4); border: 1px solid var(--dn-border-strong); border-radius: var(--dn-radius); background: var(--dn-bg-raised); color: var(--dn-fg); font-size: var(--dn-text-base); font-weight: 500; transition: background-color var(--dn-dur-fast) var(--dn-ease), border-color var(--dn-dur-fast) var(--dn-ease); } .btn:hover:not(:disabled) { background: var(--dn-bg-overlay); border-color: var(--ctp-surface-2); } .btn-primary { background: var(--dn-accent); border-color: var(--dn-accent); color: var(--dn-fg-on-accent); } .btn-primary:hover:not(:disabled) { background: var(--dn-accent-hover); border-color: var(--dn-accent-hover); } .btn-ghost { background: transparent; border-color: transparent; } .btn-ghost:hover:not(:disabled) { background: var(--dn-bg-raised); border-color: transparent; } /* --- Text input -------------------------------------------------------------- Workspace names, file names, search. -------------------------------------------------------------------------- */ .input { width: 100%; padding: var(--dn-space-2) var(--dn-space-3); border: 1px solid var(--dn-border-strong); border-radius: var(--dn-radius); background: var(--dn-bg-well); color: var(--dn-fg); font-family: var(--dn-font-code); font-size: var(--dn-text-base); transition: border-color var(--dn-dur-fast) var(--dn-ease); } .input:focus { border-color: var(--dn-accent); outline: none; } .input:focus-visible { outline: 2px solid var(--dn-accent-muted); outline-offset: 0; } /* --- Field ------------------------------------------------------------------- */ .field { display: flex; flex-direction: column; gap: var(--dn-space-2); } .field-label { color: var(--dn-fg-muted); font-family: var(--dn-font-code); font-size: var(--dn-text-xs); letter-spacing: var(--dn-tracking-caps); text-transform: uppercase; } .field-hint { color: var(--dn-fg-faint); font-size: var(--dn-text-xs); } .field-error { color: var(--dn-danger); font-size: var(--dn-text-xs); } /* --- Empty state -------------------------------------------------------------- An empty screen is an invitation to act, not a shrug. -------------------------------------------------------------------------- */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--dn-space-3); height: 100%; padding: var(--dn-space-7) var(--dn-space-4); color: var(--dn-fg-muted); text-align: center; } .empty-state-title { color: var(--dn-fg); font-size: var(--dn-text-md); font-weight: 600; } /* --- Workspace-Listeneintrag --------------------------------------------------- Ordnername, darunter der Pfad, rechts bei Bedarf ein Statusabzeichen. Ein defekter Eintrag wird gedämpft, bleibt aber anklickbar: Ein Klick versucht es erneut, womit „Stick wieder eingesteckt" ohne eigenen Knopf abgedeckt ist. -------------------------------------------------------------------------- */ .ws-list { display: flex; flex-direction: column; gap: 1px; } .ws-item { display: flex; align-items: center; gap: var(--dn-space-3); width: 100%; padding: var(--dn-space-3); border: 0; border-radius: var(--dn-radius); background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; transition: background-color var(--dn-dur-fast) var(--dn-ease); } .ws-item:hover { background: var(--dn-bg-raised); } .ws-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; } .ws-item-name { color: var(--dn-fg); font-weight: 500; } /* Bei Überlänge vorne kürzen: Das Ende eines Pfades sagt mehr als sein Anfang. */ .ws-item-path { direction: rtl; text-align: left; color: var(--dn-fg-faint); font-family: var(--dn-font-code); font-size: var(--dn-text-xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ws-item.is-broken .ws-item-name { color: var(--dn-fg-muted); } .ws-badge { flex: none; padding: 2px var(--dn-space-2); border-radius: 999px; font-size: var(--dn-text-xs); white-space: nowrap; } /* Drei Zustände, drei Farben — sie führen zu verschiedenen Handlungen: Laufwerk einhängen, Ordner wiederherstellen, Datei reparieren. */ .ws-badge.unreachable { background: color-mix(in oklab, var(--dn-warning) 18%, transparent); color: var(--dn-warning); } .ws-badge.no-marker { background: color-mix(in oklab, var(--dn-fg-faint) 22%, transparent); color: var(--dn-fg-muted); } .ws-badge.damaged { background: color-mix(in oklab, var(--dn-danger) 18%, transparent); color: var(--dn-danger); } /* --- Dialog -------------------------------------------------------------------- Für Unterbrechungen einer laufenden Aktion. Zustände gehören dagegen inline an ihren Ort, nicht in ein zweites Fenster. -------------------------------------------------------------------------- */ .dialog-scrim { position: fixed; inset: 0; display: grid; place-items: center; padding: var(--dn-space-4); background: rgb(0 0 0 / 0.55); z-index: 50; } .dialog { width: min(28rem, 100%); display: flex; flex-direction: column; gap: var(--dn-space-4); padding: var(--dn-space-5); border: 1px solid var(--dn-border-strong); border-radius: var(--dn-radius-lg); background: var(--dn-bg-sunken); box-shadow: var(--dn-shadow); } .dialog h2 { font-size: var(--dn-text-md); font-weight: 600; } .dialog p { color: var(--dn-fg-muted); line-height: var(--dn-leading-normal); } .dialog code { font-family: var(--dn-font-code); font-size: var(--dn-text-sm); color: var(--dn-fg); overflow-wrap: anywhere; } .dialog-actions { display: flex; justify-content: flex-end; gap: var(--dn-space-2); } /* --- Utilities ---------------------------------------------------------------- */ .visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }