/* In a layer so the site's own styles (header, footer, theme) win over
Bootstrap's wherever both style the same thing. */
@import url("https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css") layer(bootstrap);
.file-renamer {
--bs-body-bg: var(--bg-sunken);
--bs-body-color: var(--text);
--bs-border-color: var(--border);
--bs-secondary-bg: var(--bg-raised);
--bs-tertiary-bg: var(--bg-raised);
}
/* The site's buttons inherit their line height, which Bootstrap's .btn sets */
.btn:where(:not(.file-renamer .btn)) {
line-height: inherit;
}
/* Undo the site styles that would otherwise beat Bootstrap's in the app */
.file-renamer .btn {
all: revert-layer;
}
.file-renamer :is(input, select, textarea, button) {
font: revert-layer;
}
.file-renamer h1 {
font-weight: 700;
}
.file-renamer .lead {
margin-bottom: 1.5rem;
font-weight: 400;
}
[v-cloak] {
display: none;
}
.file-renamer .mono {
font-family: var(--mono);
}
/* Vue drops the space between an icon and its label */
.file-renamer .btn > :is(.bi, .spinner-border) + .label {
margin-left: 0.35em;
}
.file-renamer .muted {
color: var(--muted);
}
.rename-icon {
flex: none;
width: 1em;
height: 1em;
}
.renamer-title {
display: flex;
align-items: center;
gap: 0.6rem;
}
/* ---------- Bars ---------- */
.renamer-bar,
.rename-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem 1rem;
margin-bottom: 0.75rem;
}
.folder-info {
display: flex;
align-items: center;
gap: 0.5rem;
min-width: 0;
}
.folder-info strong {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.folder-info .btn-link {
color: var(--muted);
}
.folder-info .btn-link:hover {
color: var(--text);
}
.bar-actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-left: auto;
}
.rename-group {
flex: 0 1 46rem;
}
.rename-group .form-select {
min-width: 12rem;
}
/* ---------- Renaming ---------- */
.rename-panel {
margin-bottom: 0.75rem;
}
.rename-panel .rename-bar {
margin-bottom: 0;
}
.function-inputs {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: 0.6rem 1rem;
margin-top: 0.6rem;
padding: 0.75rem 1rem;
border: 1px solid var(--border);
border-radius: 0.5rem;
background: var(--bg-raised);
}
.function-input {
display: grid;
gap: 0.2rem;
min-width: 9rem;
}
.function-input .form-control:not(.number-input) {
min-width: 14rem;
}
.function-input .number-input {
width: 6.5rem;
}
.function-input-label {
color: var(--muted);
font-size: 0.8rem;
font-weight: 600;
}
.function-input-label .required {
margin-left: 0.15em;
color: var(--danger-text);
}
.function-check {
margin-bottom: 0.3rem;
}
.inputs-hint,
.inputs-warning {
flex-basis: 100%;
margin: 0;
font-size: 0.85rem;
}
.inputs-hint {
color: var(--muted);
}
.inputs-warning {
color: var(--warning-text);
}
.rename-hint {
color: var(--warning-text);
font-size: 0.9rem;
}
.notice {
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.notice-text {
white-space: pre-line;
}
.notice-actions {
display: flex;
flex-wrap: wrap;
flex: none;
align-self: center;
gap: 0.4rem;
}
/* ---------- Panes ---------- */
.panes {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1rem;
/* Fill the window below the bars, but never get cramped */
height: max(26rem, calc(100vh - 22rem));
}
.panes.has-code {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
.pane {
display: flex;
flex-direction: column;
min-height: 0;
border: 1px solid var(--border);
border-radius: 0.5rem;
background: var(--bg-raised);
overflow: hidden;
}
.pane-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem;
min-height: 3rem;
padding: 0.5rem 0.75rem;
border-bottom: 1px solid var(--border);
}
.pane-title {
margin: 0 0.25rem 0 0;
font-size: 1rem;
font-weight: 600;
}
.pane-note {
color: var(--muted);
font-size: 0.85rem;
}
.pane-actions {
display: flex;
align-items: center;
gap: 0.35rem;
margin-left: auto;
font-size: 0.9rem;
}
/* ---------- Files ---------- */
.paths-wrap {
flex: 1;
min-height: 0;
overflow: auto;
background: var(--bg-sunken);
}
.paths-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
height: 100%;
padding: 2rem;
color: var(--muted);
text-align: center;
}
.paths-placeholder p {
max-width: 28rem;
margin: 0;
}
.paths-placeholder .rename-icon {
width: 4rem;
height: 4rem;
opacity: 0.8;
}
.paths {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
}
.paths thead th {
position: sticky;
top: 0;
z-index: 2;
padding: 0.5rem 0.75rem;
border-bottom: 1px solid var(--border);
background: var(--bg-raised);
font-size: 0.8rem;
font-weight: 600;
text-align: left;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--muted);
}
.paths td {
width: 50%;
padding: 0.4rem 0.75rem;
border-bottom: 1px solid var(--border);
vertical-align: top;
overflow-wrap: anywhere;
}
.paths tbody tr:not(.group-row):hover td {
background: color-mix(in srgb, var(--bg-raised) 70%, transparent);
}
.paths .group-row th {
position: sticky;
top: 2.1rem;
z-index: 1;
padding: 0.45rem 0.75rem;
border-bottom: 1px solid var(--border);
background: var(--bg-raised);
font-weight: 600;
}
.group-changed th {
color: var(--success-text);
}
.group-problems th {
color: var(--danger-text);
}
.group-unchanged th {
color: var(--muted);
}
.paths mark {
padding: 0 0.1em;
border-radius: 0.2em;
background: color-mix(in srgb, var(--success-text) 22%, transparent);
color: inherit;
}
.paths .is-problem mark {
background: color-mix(in srgb, var(--danger-text) 22%, transparent);
}
.th-hint {
margin-left: 0.4rem;
font-weight: 400;
text-transform: none;
letter-spacing: 0;
opacity: 0.8;
}
.renamed-cell {
cursor: text;
}
.renamed-line {
display: flex;
align-items: flex-start;
gap: 0.5rem;
}
.renamed-text {
flex: 1;
min-width: 0;
}
.edit-button,
.edited-reset {
flex: none;
padding: 0 0.2rem;
border: 0;
border-radius: 0.25rem;
background: none;
color: var(--muted);
line-height: 1.3;
}
.edit-button {
opacity: 0;
}
.paths tr:hover .edit-button,
.edit-button:focus-visible {
opacity: 1;
}
.edit-button:hover,
.edited-reset:hover {
color: var(--text);
background: var(--bg-raised);
}
.edited-badge {
display: inline-flex;
flex: none;
align-items: center;
gap: 0.1rem;
padding: 0 0 0 0.45rem;
border: 1px solid color-mix(in srgb, var(--info-text) 45%, transparent);
border-radius: 999px;
color: var(--info-text);
font-family: var(--font);
font-size: 0.75rem;
}
.edited-badge .edited-reset {
color: inherit;
}
.renamed-cell.is-editing {
padding-top: 0.2rem;
padding-bottom: 0.2rem;
}
.edit-input {
font-size: 0.85rem;
}
.row-problem {
margin-top: 0.2rem;
color: var(--danger-text);
font-family: var(--font);
}
/* ---------- Code ---------- */
.editor-wrap {
position: relative;
flex: 1;
min-height: 0;
}
.editor {
position: absolute;
inset: 0;
}
.file-renamer .ace_editor {
font-family: var(--mono);
font-size: 13.5px;
}
/* Match the site's colors rather than the theme's */
.file-renamer .ace_editor,
.file-renamer .ace_gutter {
background: var(--bg-sunken);
}
.file-renamer .ace_gutter {
color: var(--muted);
}
.code-help {
padding: 0.5rem 0.75rem;
border-top: 1px solid var(--border);
font-size: 0.85rem;
}
.code-help summary {
color: var(--muted);
cursor: pointer;
}
.code-help p {
margin: 0.5rem 0 0.25rem;
}
/* ---------- Dialog ---------- */
.renamer-dialog {
width: min(34rem, calc(100vw - 2rem));
padding: 0;
border: 1px solid var(--border-strong);
border-radius: 0.75rem;
background: var(--bg-raised);
color: var(--text);
box-shadow: 0 24px 60px var(--shadow);
}
.renamer-dialog::backdrop {
background: rgb(0 0 0 / 0.55);
backdrop-filter: blur(2px);
}
.renamer-dialog[open] {
animation: dialog-in 0.15s ease-out;
}
@keyframes dialog-in {
from {
opacity: 0;
transform: translateY(0.5rem) scale(0.98);
}
}
@media (prefers-reduced-motion: reduce) {
.renamer-dialog[open] {
animation: none;
}
}
.renamer-dialog form {
padding: 1.25rem 1.5rem;
}
.dialog-title {
margin: 0 0 0.5rem;
font-size: 1.25rem;
font-weight: 700;
}
.dialog-message {
margin: 0;
color: var(--muted);
}
.dialog-changes {
display: grid;
gap: 0.5rem;
max-height: 50vh;
margin: 1rem 0 0;
padding: 0.75rem 0.9rem;
overflow: auto;
border: 1px solid var(--border);
border-radius: 0.5rem;
background: var(--bg-sunken);
font-size: 0.85rem;
list-style: none;
}
.dialog-changes li {
display: grid;
overflow-wrap: anywhere;
}
.dialog-changes .from {
color: var(--muted);
}
.dialog-changes .to .bi {
color: var(--success-text);
}
.dialog-more {
color: var(--muted);
font-style: italic;
}
.dialog-buttons {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
margin-top: 1.25rem;
}
@media (max-width: 900px) {
.panes.has-code {
grid-template-columns: minmax(0, 1fr);
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
height: max(40rem, calc(100vh - 14rem));
}
}
@media (max-width: 600px) {
.bar-actions {
margin-left: 0;
}
.pane-actions .label {
display: none;
}
}