@use 'variables' as *; @use 'mixins' as *; // Plugin UI renderer layout classes. // // Dynamic values are passed via CSS custom properties set on the element. // The layout rules here consume those properties via var() so the renderer // never injects full CSS rule strings. // Page wrapper .plugin-page { padding: $space-8 $space-12; max-width: 100%; overflow-x: hidden; } .plugin-page-title { font-size: $font-size-xl; font-weight: $font-weight-semibold; color: $text-0; margin: 0 0 $space-8; } // Container: vertical flex column with configurable gap and padding. .plugin-container { display: flex; flex-direction: column; gap: var(--plugin-gap, 0px); padding: var(--plugin-padding, 0); } // Grid: CSS grid with a configurable column count and gap. .plugin-grid { display: grid; grid-template-columns: repeat(var(--plugin-columns, 1), 1fr); gap: var(--plugin-gap, 0px); } // Flex: display:flex driven by data-* attribute selectors. // The gap is a CSS custom property; direction/justify/align/wrap are // plain enum strings placed in data attributes by the renderer. .plugin-flex { display: flex; gap: var(--plugin-gap, 0px); &[data-direction='row'] { flex-direction: row; } &[data-direction='column'] { flex-direction: column; } &[data-justify='flex-start'] { justify-content: flex-start; } &[data-justify='flex-end'] { justify-content: flex-end; } &[data-justify='center'] { justify-content: center; } &[data-justify='space-between'] { justify-content: space-between; } &[data-justify='space-around'] { justify-content: space-around; } &[data-justify='space-evenly'] { justify-content: space-evenly; } &[data-align='flex-start'] { align-items: flex-start; } &[data-align='flex-end'] { align-items: flex-end; } &[data-align='center'] { align-items: center; } &[data-align='stretch'] { align-items: stretch; } &[data-align='baseline'] { align-items: baseline; } &[data-wrap='wrap'] { flex-wrap: wrap; } &[data-wrap='nowrap'] { flex-wrap: nowrap; } } // Split: side-by-side sidebar + main area. .plugin-split { display: flex; } // Sidebar width is driven by --plugin-sidebar-width. .plugin-split-sidebar { width: var(--plugin-sidebar-width, 200px); flex-shrink: 0; } .plugin-split-main { flex: 1; min-width: 0; } // Card .plugin-card { background: $bg-2; border: 1px solid $border; border-radius: $radius-md; overflow: hidden; } .plugin-card-header { padding: $space-6 $space-8; font-size: $font-size-md; font-weight: $font-weight-semibold; color: $text-0; border-bottom: 1px solid $border; background: $bg-3; } .plugin-card-content { padding: $space-8; } .plugin-card-footer { padding: $space-6 $space-8; border-top: 1px solid $border; background: $bg-1; } // Typography .plugin-heading { color: $text-0; margin: 0; line-height: $line-height-tight; &.level-1 { font-size: $font-size-6xl; font-weight: $font-weight-bold; } &.level-2 { font-size: $font-size-4xl; font-weight: $font-weight-semibold; } &.level-3 { font-size: $font-size-3xl; font-weight: $font-weight-semibold; } &.level-4 { font-size: $font-size-xl; font-weight: $font-weight-medium; } &.level-5 { font-size: $font-size-lg; font-weight: $font-weight-medium; } &.level-6 { font-size: $font-size-md; font-weight: $font-weight-medium; } } .plugin-text { margin: 0; font-size: $font-size-md; color: $text-0; line-height: $line-height-normal; &.text-secondary { color: $text-1; } &.text-error { color: $error-text; } &.text-success { color: $success; } &.text-warning { color: $warning; } &.text-bold { font-weight: $font-weight-semibold; } &.text-italic { font-style: italic; } &.text-small { font-size: $font-size-sm; } &.text-large { font-size: $font-size-2xl; } } .plugin-code { background: $bg-1; border: 1px solid $border; border-radius: $radius; padding: $space-8 $space-12; font-family: $font-family-mono; font-size: $font-size-md; color: $text-0; overflow-x: auto; white-space: pre; code { font-family: inherit; font-size: inherit; color: inherit; } } // Tabs .plugin-tabs { display: flex; flex-direction: column; } .plugin-tab-list { display: flex; gap: 2px; border-bottom: 1px solid $border; margin-bottom: $space-8; } .plugin-tab { padding: $space-4 $space-10; font-size: $font-size-md; font-weight: $font-weight-medium; color: $text-1; background: transparent; border: none; border-bottom: 2px solid transparent; cursor: pointer; transition: color $transition-base, border-color $transition-base; &:hover { color: $text-0; } &.active { color: $accent-text; border-bottom-color: $accent; } .tab-icon { margin-right: $space-2; } } .plugin-tab-panels {} .plugin-tab-panel { &:not(.active) { display: none; } } // Description list .plugin-description-list-wrapper { width: 100%; } .plugin-description-list { display: grid; grid-template-columns: max-content 1fr; gap: $space-2 $space-8; margin: 0; padding: 0; dt { font-size: $font-size-sm; font-weight: $font-weight-medium; color: $text-1; text-transform: uppercase; letter-spacing: $letter-spacing-uppercase; padding: $space-3 0; white-space: nowrap; } dd { font-size: $font-size-md; color: $text-0; padding: $space-3 0; margin: 0; word-break: break-word; } &.horizontal { display: flex; flex-wrap: wrap; gap: $space-8 $space-12; dt { width: auto; padding: 0; } dd { width: auto; padding: 0; } // Pair dt+dd side by side dt, dd { display: inline; } // Each dt/dd pair sits in its own flex group via a wrapper approach. // Since we can't group them, use a two-column repeat trick instead. display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); dt { font-size: $font-size-xs; text-transform: uppercase; letter-spacing: $letter-spacing-uppercase; color: $text-2; margin-bottom: $space-1; } dd { font-size: $font-size-lg; font-weight: $font-weight-semibold; color: $text-0; } } } // Data table .plugin-data-table-wrapper { overflow-x: auto; } .plugin-data-table { width: 100%; border-collapse: collapse; font-size: $font-size-md; thead { tr { border-bottom: 1px solid $border-strong; } th { padding: $space-4 $space-6; text-align: left; font-size: $font-size-sm; font-weight: $font-weight-semibold; color: $text-1; text-transform: uppercase; letter-spacing: $letter-spacing-uppercase; white-space: nowrap; } } tbody { tr { border-bottom: 1px solid $border-subtle; transition: background $transition-fast; &:hover { background: $overlay-light; } &:last-child { border-bottom: none; } } td { padding: $space-4 $space-6; color: $text-0; vertical-align: middle; } } } // Table column with a plugin-specified fixed width. .plugin-col-constrained { width: var(--plugin-col-width); } .table-filter { margin-bottom: $space-6; input { width: 240px; padding: $space-3 $space-6; background: $bg-1; border: 1px solid $border; border-radius: $radius; color: $text-0; font-size: $font-size-md; &::placeholder { color: $text-2; } &:focus { outline: none; border-color: $accent; } } } .table-pagination { display: flex; align-items: center; gap: $space-6; padding: $space-4 0; font-size: $font-size-md; color: $text-1; } .row-actions { white-space: nowrap; width: 1%; .plugin-button { padding: $space-2 $space-4; font-size: $font-size-sm; margin-right: $space-2; } } // Media grid: reuses column/gap variables from plugin-grid. .plugin-media-grid { display: grid; grid-template-columns: repeat(var(--plugin-columns, 2), 1fr); gap: var(--plugin-gap, 8px); } .media-grid-item { background: $bg-2; border: 1px solid $border; border-radius: $radius-md; overflow: hidden; display: flex; flex-direction: column; } .media-grid-img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; } .media-grid-no-img { width: 100%; aspect-ratio: 16 / 9; background: $bg-3; display: flex; align-items: center; justify-content: center; font-size: $font-size-sm; color: $text-2; } .media-grid-caption { padding: $space-4 $space-6; font-size: $font-size-sm; color: $text-0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } // List .plugin-list-wrapper {} .plugin-list { list-style: none; margin: 0; padding: 0; } .plugin-list-item { padding: $space-4 0; } .plugin-list-divider { border: none; border-top: 1px solid $border-subtle; margin: 0; } .plugin-list-empty { padding: $space-8; text-align: center; color: $text-2; font-size: $font-size-md; } // Interactive: buttons .plugin-button { display: inline-flex; align-items: center; gap: $space-3; padding: $space-4 $space-8; border: 1px solid $border; border-radius: $radius; font-size: $font-size-md; font-weight: $font-weight-medium; cursor: pointer; transition: background $transition-fast, border-color $transition-fast, color $transition-fast; background: $bg-2; color: $text-0; &:disabled { opacity: 0.45; cursor: not-allowed; } &.btn-primary { background: $accent; border-color: $accent; color: #fff; &:hover:not(:disabled) { background: $accent-hover; } } &.btn-secondary { background: $bg-3; border-color: $border-strong; color: $text-0; &:hover:not(:disabled) { background: $overlay-medium; } } &.btn-tertiary { background: transparent; border-color: transparent; color: $accent-text; &:hover:not(:disabled) { background: $accent-dim; } } &.btn-danger { background: transparent; border-color: $error-border; color: $error-text; &:hover:not(:disabled) { background: $error-bg; } } &.btn-success { background: transparent; border-color: $success-border; color: $success; &:hover:not(:disabled) { background: $success-bg; } } &.btn-ghost { background: transparent; border-color: transparent; color: $text-1; &:hover:not(:disabled) { background: $btn-ghost-hover; } } } // Badges .plugin-badge { display: inline-flex; align-items: center; padding: $space-1 $space-4; border-radius: $radius-full; font-size: $font-size-xs; font-weight: $font-weight-semibold; letter-spacing: $letter-spacing-uppercase; text-transform: uppercase; &.badge-default, &.badge-neutral { background: $overlay-medium; color: $text-1; } &.badge-primary { background: $accent-dim; color: $accent-text; } &.badge-secondary { background: $overlay-light; color: $text-0; } &.badge-success { background: $success-bg; color: $success; } &.badge-warning { background: $warning-bg; color: $warning; } &.badge-error { background: $error-bg; color: $error-text; } &.badge-info { background: $info-bg; color: $accent-text; } } // Form .plugin-form { display: flex; flex-direction: column; gap: $space-8; } .form-field { display: flex; flex-direction: column; gap: $space-3; label { font-size: $font-size-md; font-weight: $font-weight-medium; color: $text-0; } input, textarea, select { padding: $space-4 $space-6; background: $bg-1; border: 1px solid $border; border-radius: $radius; color: $text-0; font-size: $font-size-md; font-family: inherit; &::placeholder { color: $text-2; } &:focus { outline: none; border-color: $accent; box-shadow: 0 0 0 2px $accent-dim; } } textarea { min-height: 80px; resize: vertical; } select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23a0a0b8' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right $space-6 center; padding-right: $space-16; } } .form-help { margin: 0; font-size: $font-size-sm; color: $text-2; } .form-actions { display: flex; gap: $space-6; padding-top: $space-4; } .required { color: $error; } // Link .plugin-link { color: $accent-text; text-decoration: none; &:hover { text-decoration: underline; } } .plugin-link-blocked { color: $text-2; text-decoration: line-through; cursor: not-allowed; } // Progress .plugin-progress { background: $bg-1; border: 1px solid $border; border-radius: $radius; height: 8px; overflow: hidden; display: flex; align-items: center; gap: $space-4; } .plugin-progress-bar { height: 100%; background: $accent; border-radius: 4px; transition: width 0.3s ease; width: var(--plugin-progress, 0%); } .plugin-progress-label { font-size: $font-size-sm; color: $text-1; white-space: nowrap; flex-shrink: 0; } // Chart wrapper: height is driven by --plugin-chart-height. .plugin-chart { overflow: auto; height: var(--plugin-chart-height, 200px); .chart-title { font-size: $font-size-lg; font-weight: $font-weight-semibold; color: $text-0; margin-bottom: $space-4; } .chart-x-label, .chart-y-label { font-size: $font-size-sm; color: $text-2; margin-bottom: $space-2; } .chart-data-table { overflow-x: auto; } .chart-no-data { padding: $space-12; text-align: center; color: $text-2; font-size: $font-size-md; } } // Loading / error states .plugin-loading { padding: $space-8; color: $text-1; font-size: $font-size-md; font-style: italic; } .plugin-error { padding: $space-6 $space-8; background: $error-bg; border: 1px solid $error-border; border-radius: $radius; color: $error-text; font-size: $font-size-md; } // Feedback toast .plugin-feedback { position: sticky; bottom: $space-8; display: flex; align-items: center; justify-content: space-between; gap: $space-8; padding: $space-6 $space-8; border-radius: $radius-md; font-size: $font-size-md; z-index: $z-toast; box-shadow: $shadow-lg; &.success { background: $success-bg; border: 1px solid $success-border; color: $success; } &.error { background: $error-bg; border: 1px solid $error-border; color: $error-text; } } .plugin-feedback-dismiss { background: transparent; border: none; color: inherit; font-size: $font-size-xl; cursor: pointer; line-height: 1; padding: 0; opacity: 0.7; &:hover { opacity: 1; } } // Modal .plugin-modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.65); display: flex; align-items: center; justify-content: center; z-index: $z-modal-backdrop; } .plugin-modal { position: relative; background: $bg-2; border: 1px solid $border-strong; border-radius: $radius-xl; padding: $space-16; min-width: 380px; max-width: 640px; max-height: 80vh; overflow-y: auto; box-shadow: $shadow-lg; z-index: $z-modal; } .plugin-modal-close { position: absolute; top: $space-8; right: $space-8; background: transparent; border: none; color: $text-1; font-size: $font-size-xl; cursor: pointer; line-height: 1; padding: $space-2; border-radius: $radius; &:hover { background: $overlay-medium; color: $text-0; } }