/* * Raiju Admin — Unified Component Library * All classes prefixed with rj- to avoid collision with frontend site CSS. * Requires: raiju-admin-tokens.css */ /* ============================================================ ADMIN SURFACES ============================================================ */ .rj-admin-panel, .rj-admin-group, .rj-admin-item { color: var(--rj-text); border: 1px solid var(--rj-border); box-shadow: none; } .rj-admin-panel { background: var(--rj-surface-panel, var(--rj-bg-elevated)); border-radius: var(--rj-radius-lg); padding: var(--rj-space-5) var(--rj-space-6); } .rj-admin-group { background: var(--rj-surface-group, color-mix(in srgb, var(--rj-bg-elevated) 88%, var(--rj-bg))); border-radius: var(--rj-radius-lg); padding: var(--rj-space-4) var(--rj-space-5); } .rj-admin-item { background: var(--rj-surface-item, var(--rj-bg)); border-radius: var(--rj-radius-md); padding: var(--rj-space-3); } .rj-admin-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--rj-space-2); } .rj-admin-icon-button { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 1px solid var(--rj-border); border-radius: var(--rj-radius-md); background: var(--rj-bg-elevated); color: var(--rj-text-muted); cursor: pointer; transition: background-color var(--rj-duration-fast) var(--rj-ease), border-color var(--rj-duration-fast) var(--rj-ease), color var(--rj-duration-fast) var(--rj-ease), transform var(--rj-duration-fast) var(--rj-ease); } .rj-admin-icon-button:hover, .rj-admin-icon-button:focus-visible { background: var(--rj-bg-hover); border-color: var(--rj-border-strong); color: var(--rj-text); outline: none; } .rj-admin-icon-button:focus-visible { box-shadow: 0 0 0 3px var(--rj-focus-ring, var(--rj-primary-muted)); } .rj-admin-icon-button:active { transform: scale(0.98); } .rj-admin-icon-button svg { width: 16px; height: 16px; stroke-width: 1.5; } /* ============================================================ BUTTONS ============================================================ */ .rj-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--rj-space-2); height: var(--rj-control-h, 2.5rem); padding: 0 var(--rj-space-5, 1.25rem); border: 1px solid transparent; border-radius: var(--editor-btn-radius, var(--rj-radius-md)); font-family: var(--rj-font-sans); font-size: var(--rj-text-md, 0.875rem); font-weight: 500; line-height: 1.2; cursor: pointer; transition: background-color var(--rj-duration-fast) var(--rj-ease), color var(--rj-duration-fast) var(--rj-ease), border-color var(--rj-duration-fast) var(--rj-ease), transform var(--rj-duration-fast) var(--rj-ease), box-shadow var(--rj-duration-fast) var(--rj-ease); text-decoration: none; white-space: nowrap; user-select: none; } .rj-btn:active { transform: scale(0.98); } .rj-btn:focus-visible { outline: 2px solid var(--rj-primary); outline-offset: 2px; } .rj-btn:disabled { opacity: 0.5; pointer-events: none; } /* Primary */ /* Same hover as .btn-primary in admin/style.css: lift, then settle; glow is a sheen plus shadow that .rj-flat-buttons removes */ .rj-btn--primary { --rj-hover-from: var(--rj-primary); --rj-hover-peak: var(--rj-hover-lift, var(--rj-primary-hover)); --rj-hover-to: var(--rj-hover-settle, var(--rj-primary-hover)); background-color: var(--rj-primary); background-image: var(--rj-primary-sheen, none); color: var(--rj-text-on-primary); text-shadow: 0 1px 1px rgba(255,255,255,0.25), 0 -1px 1px rgba(0,0,0,0.15); box-shadow: 0 2px 8px color-mix(in srgb, var(--rj-primary) 15%, transparent); transition: background-color var(--rj-duration-hover-out, 320ms) ease-out, box-shadow var(--rj-duration-hover-out, 320ms) ease-out, transform var(--rj-duration-fast) var(--rj-ease); } .rj-btn--primary:hover { background-color: var(--rj-hover-settle, var(--rj-primary-hover)); box-shadow: 0 4px 20px color-mix(in srgb, var(--rj-primary) 35%, transparent); animation: rj-hover-fill var(--rj-duration-hover-in, 1400ms) linear both; transition: box-shadow calc(var(--rj-duration-hover-in, 1400ms) * 0.4) var(--rj-ease), transform var(--rj-duration-fast) var(--rj-ease); } .rj-btn--primary:active { background-color: var(--rj-primary-active); animation: none; transition-duration: var(--rj-duration-press, 100ms); } .rj-flat-buttons .rj-btn--primary, .rj-flat-buttons .rj-btn--primary:hover, .rj-flat-buttons .rj-btn--primary:active { background-image: none; box-shadow: none; text-shadow: none; } .rj-btn:disabled, .rj-btn[aria-busy="true"] { animation: none; pointer-events: none; } @keyframes rj-hover-fill { 0% { background-color: var(--rj-hover-from); } 36% { background-color: var(--rj-hover-peak); } 62% { background-color: var(--rj-hover-peak); } 100% { background-color: var(--rj-hover-to); } } /* Secondary */ .rj-btn--secondary { background: var(--rj-bg-sunken); color: var(--rj-text); border-color: var(--rj-border); } .rj-btn--secondary:hover { background: var(--rj-bg-hover); border-color: var(--rj-border-strong); } /* Ghost */ .rj-btn--ghost { background: transparent; color: var(--rj-text-secondary); } .rj-btn--ghost:hover { background: var(--rj-bg-hover); color: var(--rj-text); } /* Danger */ .rj-btn--danger { background: var(--rj-danger); color: #ffffff; } .rj-btn--danger:hover { background: var(--rj-danger-hover); } /* Success */ .rj-btn--success { background: var(--rj-success); color: #ffffff; } .rj-btn--success:hover { background: #15803d; } /* Icon-only button */ .rj-btn--icon { width: var(--rj-control-h, 2.5rem); height: var(--rj-control-h, 2.5rem); padding: 0; border-radius: var(--editor-btn-radius, var(--rj-radius-md)); } /* Sizes */ .rj-btn--sm { height: var(--rj-control-h-sm, 2rem); padding: 0 var(--rj-space-3, 0.75rem); font-size: var(--rj-text-sm, 0.8125rem); } .rj-btn--sm.rj-btn--icon { width: var(--rj-control-h-sm, 2rem); } .rj-btn--block { display: flex; width: 100%; } /* ============================================================ FORM FIELDS ============================================================ */ .rj-field { margin-bottom: var(--rj-space-5); } .rj-field__label { display: block; margin-bottom: var(--rj-space-2); font-family: var(--rj-font-sans); font-size: 0.875rem; font-weight: 500; color: var(--rj-text); } .rj-field__label--optional { font-weight: 400; color: var(--rj-text-muted); } .rj-field__input, .rj-field__textarea, .rj-field__select { width: 100%; padding: 10px 14px; border: 1px solid var(--rj-border); border-radius: var(--rj-radius-md); background: var(--rj-bg-elevated); color: var(--rj-text); font-family: var(--rj-font-sans); font-size: 0.9375rem; line-height: 1.5; transition: border-color var(--rj-duration-fast) var(--rj-ease), box-shadow var(--rj-duration-fast) var(--rj-ease); } .rj-field__input::placeholder, .rj-field__textarea::placeholder { color: var(--rj-text-muted); } .rj-field__input:focus, .rj-field__textarea:focus, .rj-field__select:focus { outline: none; border-color: var(--rj-primary); box-shadow: 0 0 0 3px var(--rj-primary-muted); } .rj-field__textarea { min-height: 80px; resize: vertical; } .rj-field__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 1.5l5 5 5-5' stroke='%23525252' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; padding-right: 40px; } .rj-field__hint { display: block; margin-top: var(--rj-space-1); font-family: var(--rj-font-sans); font-size: 0.8125rem; color: var(--rj-text-muted); line-height: 1.4; } .rj-field__hint code { background: var(--rj-bg-sunken); padding: 1px 5px; border-radius: var(--rj-radius-sm); font-family: var(--rj-font-mono); font-size: 0.8em; } .rj-field__error { display: block; margin-top: var(--rj-space-1); font-family: var(--rj-font-sans); font-size: 0.8125rem; color: var(--rj-danger); line-height: 1.4; } /* ============================================================ CARDS ============================================================ */ .rj-card { background: var(--rj-bg-elevated); border: 1px solid var(--rj-border); border-radius: var(--rj-radius-lg); box-shadow: none; } .rj-card__header { padding: var(--rj-space-5) var(--rj-space-6); border-bottom: 1px solid var(--rj-border); display: flex; align-items: center; justify-content: space-between; } .rj-card__header h2, .rj-card__header h3 { margin: 0; font-family: var(--rj-font-sans); font-weight: 600; color: var(--rj-text); } .rj-card__body { padding: var(--rj-space-5) var(--rj-space-6); } .rj-card--flat { box-shadow: none; } /* ============================================================ TABS (Pill-style) ============================================================ */ .rj-tabs { display: flex; align-items: center; gap: var(--rj-space-1); } .rj-tab { position: relative; padding: 8px 16px; border: none; border-radius: var(--rj-radius-full); background: transparent; color: var(--rj-text-secondary); font-family: var(--rj-font-sans); font-size: 0.875rem; font-weight: 500; cursor: pointer; transition: background-color var(--rj-duration-fast) var(--rj-ease), color var(--rj-duration-fast) var(--rj-ease); white-space: nowrap; } .rj-tab:hover { background: var(--rj-bg-hover); color: var(--rj-text); } .rj-tab:focus-visible { outline: 2px solid var(--rj-primary); outline-offset: 2px; } .rj-tab--active { background: var(--rj-primary-subtle); color: var(--rj-primary); } .rj-tab--active:hover { background: var(--rj-primary-muted); } /* ============================================================ BADGE ============================================================ */ .rj-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--rj-radius-full); background: var(--rj-danger); color: #ffffff; font-family: var(--rj-font-sans); font-size: 0.6875rem; font-weight: 600; line-height: 1; } /* ============================================================ MODALS ============================================================ */ .rj-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: var(--rj-z-modal); display: none; } .rj-modal.active { display: block; } .rj-modal__backdrop { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); animation: rj-fade-in var(--rj-duration-normal) var(--rj-ease); } .rj-modal__dialog { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--rj-bg-elevated); border-radius: var(--rj-radius-lg); box-shadow: var(--rj-shadow-xl); width: 90%; max-width: 550px; max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; animation: rj-slide-in var(--rj-duration-normal) var(--rj-ease); } .rj-modal--sm .rj-modal__dialog { max-width: 400px; } .rj-modal--lg .rj-modal__dialog { max-width: 700px; } .rj-modal--xl .rj-modal__dialog { max-width: 900px; } .rj-modal__header { padding: var(--rj-space-4) var(--rj-space-5); border-bottom: 1px solid var(--rj-border); display: flex; align-items: center; justify-content: space-between; } .rj-modal__header h3 { margin: 0; font-family: var(--rj-font-sans); font-size: 1.125rem; font-weight: 600; color: var(--rj-text); } .rj-modal__close { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border: none; border-radius: var(--rj-radius-md); background: transparent; color: var(--rj-text-muted); font-size: 1.25rem; cursor: pointer; transition: background-color var(--rj-duration-fast) var(--rj-ease), color var(--rj-duration-fast) var(--rj-ease); } .rj-modal__close:hover { background: var(--rj-bg-hover); color: var(--rj-text); } .rj-modal__body { padding: var(--rj-space-5); overflow-y: auto; flex: 1; } .rj-modal__footer { display: flex; justify-content: flex-end; gap: var(--rj-space-2); padding: var(--rj-space-4) var(--rj-space-5); border-top: 1px solid var(--rj-border); background: var(--rj-bg-sunken); border-radius: 0 0 var(--rj-radius-lg) var(--rj-radius-lg); } /* ============================================================ TOASTS ============================================================ */ .rj-toast { position: fixed; bottom: var(--rj-space-5); right: var(--rj-space-5); z-index: var(--rj-z-toast); display: flex; align-items: center; gap: var(--rj-space-3); padding: var(--rj-space-3) var(--rj-space-5); background: var(--rj-bg-elevated); border: 1px solid var(--rj-border); border-left: 4px solid var(--rj-primary); border-radius: var(--rj-radius-md); box-shadow: var(--rj-shadow-lg); color: var(--rj-text); font-family: var(--rj-font-sans); font-size: 0.875rem; animation: rj-slide-in-right var(--rj-duration-normal) var(--rj-ease); } .rj-toast--success { border-left-color: var(--rj-success); } .rj-toast--error { border-left-color: var(--rj-danger); } .rj-toast--info { border-left-color: var(--rj-primary); } /* ============================================================ ALERTS / MESSAGES ============================================================ */ .rj-alert { padding: var(--rj-space-3) var(--rj-space-4); border-radius: var(--rj-radius-md); font-family: var(--rj-font-sans); font-size: 0.875rem; line-height: 1.5; margin-bottom: var(--rj-space-5); } .rj-alert--error { background: var(--rj-danger-subtle); color: var(--rj-danger); border: 1px solid rgba(220, 38, 38, 0.15); } .rj-alert--success { background: var(--rj-success-subtle); color: var(--rj-success); border: 1px solid rgba(22, 163, 74, 0.15); } .rj-alert--warning { background: var(--rj-warning-subtle); color: var(--rj-warning); border: 1px solid rgba(217, 119, 6, 0.15); } /* ============================================================ ANIMATIONS ============================================================ */ @keyframes rj-fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes rj-slide-in { from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } } @keyframes rj-slide-in-right { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: translateX(0); } }