/* ==========================================================================
   Image Panel — shared dashboard styles
   Plain CSS, served statically from /css/app.css (no build step required).
   ========================================================================== */

:root {
    --sidebar-width: 260px;
    --header-height: 64px;

    --color-bg: #f1f5f9;
    --color-surface: #ffffff;
    --color-border: #e2e8f0;

    --color-text: #0f172a;
    --color-muted: #64748b;

    --color-primary: #4f46e5;
    --color-primary-dark: #4338ca;
    --color-primary-soft: #eef2ff;

    --color-success: #059669;
    --color-success-soft: #d1fae5;
    --color-danger: #dc2626;
    --color-danger-soft: #fee2e2;
    --color-warning: #d97706;
    --color-warning-soft: #fef3c7;

    --color-sidebar: #0f172a;
    --color-sidebar-hover: #1e293b;
    --color-sidebar-text: #cbd5e1;

    --radius: 10px;
    --radius-sm: 6px;
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
    --shadow: 0 4px 12px rgba(15, 23, 42, 0.08);
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

/*
   The hidden attribute has to beat author display rules.

   .hist-grid sets display: grid, and any author declaration outranks the
   browser's own [hidden] { display: none }. Without this line the gallery and
   the table render on top of each other, because hidden has no effect at all.
*/
[hidden] {
    display: none !important;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
    font-size: 15px;
    line-height: 1.55;
    color: var(--color-text);
    background: var(--color-bg);
}

a {
    color: var(--color-primary);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

h1,
h2,
h3 {
    margin: 0 0 0.4rem;
    line-height: 1.25;
    font-weight: 700;
}

h1 {
    font-size: 1.5rem;
}

h2 {
    font-size: 1.15rem;
}

h3 {
    font-size: 1rem;
}

p {
    margin: 0 0 0.75rem;
}

/* --------------------------------------------------------------- Layout -- */

.layout {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    width: var(--sidebar-width);
    flex: 0 0 var(--sidebar-width);
    background: var(--color-sidebar);
    color: var(--color-sidebar-text);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    z-index: 40;
}

.sidebar__brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 1.15rem 1.25rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    color: #fff;
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
}

.sidebar__brand:hover {
    text-decoration: none;
}

.sidebar__logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--radius-sm);
    background: var(--color-primary);
    color: #fff;
    font-weight: 800;
    font-size: 0.95rem;
    flex: 0 0 auto;
}

.sidebar__section {
    padding: 1.1rem 1.25rem 0.4rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #64748b;
}

.sidebar__nav {
    list-style: none;
    margin: 0;
    padding: 0 0.75rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.sidebar__link {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.6rem 0.75rem;
    border-radius: var(--radius-sm);
    color: var(--color-sidebar-text);
    font-size: 0.9rem;
    font-weight: 500;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.sidebar__link:hover {
    background: var(--color-sidebar-hover);
    color: #fff;
    text-decoration: none;
}

.sidebar__link.is-active {
    background: var(--color-primary);
    color: #fff;
}

/* Area switch button - navigation only, visually distinct from normal links. */
.sidebar__link--switch {
    border: 1px dashed rgba(148, 163, 184, 0.5);
    background: rgba(255, 255, 255, 0.04);
    font-weight: 600;
}

.sidebar__link--switch:hover {
    background: var(--color-primary);
    border-color: var(--color-primary);
    border-style: solid;
}

.sidebar__icon {
    width: 18px;
    text-align: center;
    flex: 0 0 18px;
    opacity: 0.9;
}

.sidebar__footer {
    margin-top: auto;
    padding: 1rem 1.25rem;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    font-size: 0.8rem;
    color: #64748b;
}

.sidebar__close {
    display: none;
}

/* --------------------------------------------------------------- Main -- */

.main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.header {
    height: var(--header-height);
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0 1.5rem;
    position: sticky;
    top: 0;
    z-index: 30;
}

.header__title {
    font-size: 1.05rem;
    font-weight: 700;
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.header__spacer {
    flex: 1 1 auto;
}

.header__user {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-width: 0;
}

.header__user-name {
    font-weight: 600;
    font-size: 0.88rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.header__user-role {
    font-size: 0.72rem;
    color: var(--color-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.85rem;
    flex: 0 0 auto;
}

.content {
    padding: 1.75rem;
    flex: 1 1 auto;
    /*
       Caps the workspace on ultrawide monitors. Without this the two column
       generator stretches to 2560px and the settings inputs become absurdly
       wide, while the image preview shrinks relative to the form.
    */
    width: 100%;
    max-width: 1720px;
    margin-inline: auto;
}

.content__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.25rem;
}

.content__subtitle {
    color: var(--color-muted);
    font-size: 0.9rem;
    margin: 0;
}

/* ------------------------------------------------------------ Cards -- */

.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    margin-bottom: 1.25rem;
    overflow: hidden;
}

.card__header {
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.card__header h2,
.card__header h3 {
    margin: 0;
}

.card__body {
    padding: 1.25rem;
}

.card__footer {
    padding: 0.9rem 1.25rem;
    border-top: 1px solid var(--color-border);
    background: #f8fafc;
}

/* ----------------------------------------------------------- Stats -- */

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.stat {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 1.1rem 1.25rem;
}

.stat__label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-muted);
    font-weight: 600;
}

.stat__value {
    font-size: 1.85rem;
    font-weight: 700;
    line-height: 1.2;
    margin-top: 0.3rem;
}

.stat__hint {
    font-size: 0.8rem;
    color: var(--color-muted);
    margin-top: 0.15rem;
}

/* ---------------------------------------------------------- Buttons -- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.55rem 1rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-size: 0.88rem;
    font-weight: 600;
    font-family: inherit;
    line-height: 1.2;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 0.15s ease, border-color 0.15s ease,
        color 0.15s ease;
}

.btn:hover {
    text-decoration: none;
}

.btn:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

.btn--primary {
    background: var(--color-primary);
    color: #fff;
}

.btn--primary:hover {
    background: var(--color-primary-dark);
    color: #fff;
}

.btn--secondary {
    background: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-text);
}

.btn--secondary:hover {
    background: #f8fafc;
    color: var(--color-text);
}

.btn--danger {
    background: var(--color-danger);
    color: #fff;
}

.btn--danger:hover {
    background: #b91c1c;
    color: #fff;
}

.btn--success {
    background: var(--color-success);
    color: #fff;
}

.btn--success:hover {
    background: #047857;
    color: #fff;
}

.btn--sm {
    padding: 0.35rem 0.65rem;
    font-size: 0.8rem;
}

.btn--block {
    width: 100%;
}

.btn-row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    align-items: center;
}

/* ----------------------------------------------------------- Forms -- */

.form-group {
    margin-bottom: 1.1rem;
}

.label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 0.35rem;
}

.label__hint {
    font-weight: 400;
    color: var(--color-muted);
    font-size: 0.8rem;
}

.input,
.select,
.textarea {
    width: 100%;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    font-family: inherit;
    color: var(--color-text);
    background: var(--color-surface);
}

.input:focus,
.select:focus,
.textarea:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

.input.is-invalid,
.select.is-invalid {
    border-color: var(--color-danger);
}

.error-text {
    display: block;
    color: var(--color-danger);
    font-size: 0.8rem;
    margin-top: 0.3rem;
}

.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0 1rem;
}

.checkbox {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.88rem;
    cursor: pointer;
}

.checkbox input {
    width: 16px;
    height: 16px;
    accent-color: var(--color-primary);
}

/* ----------------------------------------------------------- Tables -- */

.table-wrap {
    overflow-x: auto;
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
    min-width: 640px;
}

.table th,
.table td {
    padding: 0.75rem 1.25rem;
    text-align: left;
    border-bottom: 1px solid var(--color-border);
    vertical-align: middle;
}

.table th {
    background: #f8fafc;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-muted);
    font-weight: 700;
    white-space: nowrap;
}

.table tbody tr:last-child td {
    border-bottom: 0;
}

.table tbody tr:hover {
    background: #fafbff;
}

.table__actions {
    display: flex;
    gap: 0.4rem;
    justify-content: flex-end;
    flex-wrap: wrap;
}

.cell-user {
    display: flex;
    align-items: center;
    gap: 0.65rem;
}

.cell-user__meta {
    min-width: 0;
}

.cell-user__name {
    font-weight: 600;
    color: var(--color-text);
}

.cell-user__email {
    font-size: 0.8rem;
    color: var(--color-muted);
    word-break: break-all;
}

/* ----------------------------------------------------------- Badges -- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
}

.badge--success {
    background: var(--color-success-soft);
    color: #065f46;
}

.badge--danger {
    background: var(--color-danger-soft);
    color: #991b1b;
}

.badge--primary {
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
}

.badge--warning {
    background: var(--color-warning-soft);
    color: #92400e;
}

.badge--muted {
    background: #f1f5f9;
    color: var(--color-muted);
}

/* ---------------------------------------------------------- Alerts -- */

.alert {
    padding: 0.85rem 1.1rem;
    border-radius: var(--radius-sm);
    font-size: 0.88rem;
    margin-bottom: 1.25rem;
    border: 1px solid transparent;
    display: flex;
    gap: 0.6rem;
    align-items: flex-start;
}

.alert ul {
    margin: 0.25rem 0 0;
    padding-left: 1.1rem;
}

.alert--success {
    background: var(--color-success-soft);
    border-color: #a7f3d0;
    color: #065f46;
}

.alert--danger {
    background: var(--color-danger-soft);
    border-color: #fecaca;
    color: #991b1b;
}

.alert--info {
    background: var(--color-primary-soft);
    border-color: #c7d2fe;
    color: var(--color-primary-dark);
}

/* ------------------------------------------------------ Empty state -- */

.empty-state {
    text-align: center;
    padding: 2.75rem 1.5rem;
    color: var(--color-muted);
}

.empty-state__icon {
    font-size: 2.25rem;
    margin-bottom: 0.6rem;
    opacity: 0.65;
}

.empty-state__title {
    font-weight: 700;
    color: var(--color-text);
    margin-bottom: 0.3rem;
    font-size: 1rem;
}

.empty-state p {
    max-width: 420px;
    margin: 0 auto 1rem;
    font-size: 0.9rem;
}

/* ------------------------------------------------------ Description -- */

.description-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1.1rem;
    margin: 0;
}

.description-list dt {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-muted);
    font-weight: 700;
    margin-bottom: 0.2rem;
}

.description-list dd {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 500;
    word-break: break-word;
}

/* ------------------------------------------------------------ Login -- */

.auth-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: linear-gradient(135deg, #0f172a 0%, #1e293b 55%, #312e81 100%);
}

.auth-card {
    width: 100%;
    max-width: 420px;
    background: var(--color-surface);
    border-radius: 14px;
    box-shadow: 0 20px 45px rgba(2, 6, 23, 0.35);
    padding: 2rem;
}

.auth-card__brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 1.25rem;
    color: var(--color-text);
    font-weight: 700;
    font-size: 1.1rem;
}

.auth-card__brand:hover {
    text-decoration: none;
}

.auth-card__title {
    margin-bottom: 0.25rem;
}

.auth-card__subtitle {
    color: var(--color-muted);
    font-size: 0.88rem;
    margin-bottom: 1.5rem;
}

.auth-demo {
    margin-top: 1.5rem;
    padding: 0.9rem 1rem;
    background: var(--color-bg);
    border-radius: var(--radius-sm);
    font-size: 0.8rem;
    color: var(--color-muted);
}

.auth-demo strong {
    color: var(--color-text);
}

.auth-demo code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    color: var(--color-primary-dark);
}

/* ------------------------------------------------------ Pagination -- */

.pagination {
    display: flex;
    gap: 0.3rem;
    list-style: none;
    margin: 0;
    padding: 0;
    flex-wrap: wrap;
}

.pagination li {
    display: inline-flex;
}

.pagination a,
.pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    color: var(--color-text);
    background: var(--color-surface);
}

.pagination a:hover {
    background: #f8fafc;
    text-decoration: none;
}

.pagination .is-active span {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: #fff;
    font-weight: 600;
}

.pagination .is-disabled span {
    color: #cbd5e1;
    background: #f8fafc;
}

/* ------------------------------------------------------------ Gallery -- */

.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1rem;
}

.gallery__item {
    margin: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--color-surface);
}

.gallery__item img {
    display: block;
    width: 100%;
    height: 220px;
    object-fit: contain;
    background: #f8fafc;
}

.gallery__item figcaption {
    padding: 0.6rem 0.75rem;
    border-top: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    font-size: 0.78rem;
    color: var(--color-muted);
    word-break: break-all;
}

.hidden {
    display: none !important;
}

/* ------------------------------------------------------- Utilities -- */

.text-muted {
    color: var(--color-muted);
}

.text-sm {
    font-size: 0.85rem;
}

.text-right {
    text-align: right;
}

.mt-0 {
    margin-top: 0;
}

.mb-0 {
    margin-bottom: 0;
}

.mt-1 {
    margin-top: 0.75rem;
}

.divider {
    height: 1px;
    background: var(--color-border);
    border: 0;
    margin: 1.25rem 0;
}

.sidebar-toggle {
    display: none;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    width: 38px;
    height: 38px;
    cursor: pointer;
    font-size: 1.1rem;
    color: var(--color-text);
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}

.scrim {
    display: none;
}

/* ---------------------------------------------------------- Mobile -- */

@media (max-width: 900px) {
    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        transform: translateX(-100%);
        transition: transform 0.22s ease;
        box-shadow: var(--shadow);
    }

    body.nav-open .sidebar {
        transform: translateX(0);
    }

    .sidebar__close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        margin-left: auto;
        background: transparent;
        border: 0;
        color: var(--color-sidebar-text);
        font-size: 1.25rem;
        cursor: pointer;
        padding: 0 0.25rem;
    }

    .scrim {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(15, 23, 42, 0.5);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.22s ease, visibility 0.22s ease;
        z-index: 35;
    }

    body.nav-open .scrim {
        opacity: 1;
        visibility: visible;
    }

    .sidebar-toggle {
        display: inline-flex;
    }

    .content {
        padding: 1.15rem;
    }

    .header {
        padding: 0 1rem;
    }

    .header__user-meta {
        display: none;
    }

    .auth-card {
        padding: 1.5rem;
    }
}

@media (max-width: 560px) {
    .content__header {
        flex-direction: column;
        align-items: stretch;
    }

    .card__body {
        padding: 1rem;
    }

    .table th,
    .table td {
        padding: 0.65rem 0.85rem;
    }

    .stat__value {
        font-size: 1.5rem;
    }
}
/* ==========================================================================
   Generator workspace — two column layout with a live preview panel
   ========================================================================== */

.gen-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(340px, 1fr);
    gap: 1.25rem;
    align-items: start;
}

/* The preview column sticks while the settings column scrolls. */
.gen-side {
    position: sticky;
    top: calc(var(--header-height) + 1rem);
}

.gen-preview {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}

.gen-preview__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--color-border);
}

.gen-preview__title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
}

/*
   The frame always occupies space, so swapping an empty state for a real
   image never shifts the layout (CLS stays at 0).
*/
.gen-preview__frame {
    --frame-ratio: 1;
    position: relative;
    aspect-ratio: var(--frame-ratio);
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem;
    background-color: #f8fafc;
    background-image: radial-gradient(circle, #cbd5e1 1px, transparent 1px);
    background-size: 16px 16px;
    overflow: hidden;
}

.gen-preview__frame img {
    display: block;
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--radius-sm);
}

.gen-preview__state {
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 1.5rem;
    text-align: center;
    color: var(--color-muted);
}

.gen-preview[data-state='empty'] .gen-preview__state--empty,
.gen-preview[data-state='loading'] .gen-preview__state--loading,
.gen-preview[data-state='error'] .gen-preview__state--error {
    display: flex;
}

.gen-preview[data-state='ready'] .gen-preview__state {
    display: none;
}

.gen-preview__icon {
    width: 40px;
    height: 40px;
    color: var(--color-muted);
}

.gen-preview__hint {
    font-size: 0.85rem;
    max-width: 34ch;
}

.gen-preview__error {
    font-size: 0.9rem;
    color: var(--color-danger);
    font-weight: 600;
    max-width: 40ch;
}

/* Shimmer stands in for the image while the provider works. */
.gen-preview__shimmer {
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, #e2e8f0 20%, #f1f5f9 40%, #e2e8f0 60%);
    background-size: 220% 100%;
    animation: gen-shimmer 1.4s ease-in-out infinite;
}

.gen-preview[data-state='loading'] .gen-preview__shimmer {
    display: block;
}

.gen-preview[data-state='ready'] .gen-preview__shimmer,
.gen-preview[data-state='error'] .gen-preview__shimmer,
.gen-preview[data-state='empty'] .gen-preview__shimmer {
    display: none;
}

@keyframes gen-shimmer {
    from { background-position: 180% 0; }
    to { background-position: -80% 0; }
}

.gen-preview__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.7rem 1rem;
    border-top: 1px solid var(--color-border);
    font-size: 0.8rem;
    color: var(--color-muted);
}

.gen-preview__foot a {
    margin-left: auto;
}

.spinner {
    width: 22px;
    height: 22px;
    border: 2px solid var(--color-border);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: gen-spin 0.8s linear infinite;
}

@keyframes gen-spin {
    to { transform: rotate(360deg); }
}

/* ==========================================================================
   History — gallery grid, table fallback, and view toggle
   ========================================================================== */

.view-toggle {
    display: inline-flex;
    padding: 3px;
    gap: 3px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
}

.view-toggle__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    min-height: 36px;
    padding: 0.35rem 0.7rem;
    border: 0;
    border-radius: calc(var(--radius-sm) - 2px);
    background: transparent;
    color: var(--color-muted);
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.view-toggle__btn:hover {
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
}

.view-toggle__btn[aria-pressed='true'] {
    background: var(--color-primary);
    color: #ffffff;
}

.view-toggle__btn:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

.view-toggle__btn svg {
    width: 16px;
    height: 16px;
}

/* ------------------------------------------------------------ Gallery -- */

/*
   Masonry instead of a fixed square grid. Every generation keeps its own
   output ratio, so nothing is ever cropped and portrait and landscape results
   sit naturally side by side. The column count follows the viewport: one
   column on small phones, up to four on wide desktops.
*/
.hist-grid {
    columns: 4 250px;
    column-gap: 1rem;
    padding: 1rem;
}

.hist-card {
    break-inside: avoid;
    margin: 0 0 1rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}

.hist-card:hover {
    box-shadow: var(--shadow);
    border-color: #cbd5e1;
    transform: translateY(-2px);
}

/*
   The ratio comes from the recorded output size, so the box reserves exactly
   the right shape before the bytes arrive (no layout shift). object-fit is
   contain, never cover: a cropped thumbnail is what made the old grid look
   broken on portrait and landscape results.
*/
.hist-card__media {
    position: relative;
    width: 100%;
    aspect-ratio: 1;
    overflow: hidden;
    background-color: #f1f5f9;
}

.hist-card__media::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, #e2e8f0 20%, #f1f5f9 40%, #e2e8f0 60%);
    background-size: 220% 100%;
    animation: hist-shimmer 1.4s ease-in-out infinite;
    pointer-events: none;
}

@keyframes hist-shimmer {
    from { background-position: 180% 0; }
    to { background-position: -80% 0; }
}

.hist-card__media.is-done::after {
    display: none;
}

.hist-card__media a {
    display: block;
    height: 100%;
}

.hist-card__media a:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: -2px;
}

.hist-card__media img {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    transition: opacity 0.3s ease, transform 0.25s ease;
}

.hist-card__media img.is-loaded {
    opacity: 1;
}

.hist-card:hover .hist-card__media img {
    transform: scale(1.02);
}

.hist-card__status {
    position: absolute;
    top: 0.5rem;
    inset-inline-start: 0.5rem;
}

.hist-card__media--empty {
    aspect-ratio: 16 / 10;
    background: #f8fafc;
}

.hist-card__media--empty::after {
    display: none;
}

.hist-card__empty {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--color-muted);
    font-size: 0.8rem;
}

.hist-card__body {
    padding: 0.6rem 0.7rem 0.7rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.hist-card__prompt {
    font-size: 0.82rem;
    line-height: 1.4;
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.hist-card__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.72rem;
    color: var(--color-muted);
}

.hist-card__details {
    margin-inline-start: auto;
}

/* ==========================================================================
   Lightbox — full size image review
   ========================================================================== */

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 90;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
    overflow-y: auto;
    background: rgba(15, 23, 42, 0.88);
}

.lightbox[data-open='true'] {
    display: flex;
}

.lightbox__figure {
    position: relative;
    margin: auto;
    max-width: min(100%, 1200px);
    max-height: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.lightbox__figure img {
    display: block;
    max-width: 100%;
    max-height: calc(100vh - 8.5rem);
    object-fit: contain;
    margin: 0 auto;
    border-radius: var(--radius);
    background: #f8fafc;
}

.lightbox__close {
    position: absolute;
    top: -0.25rem;
    inset-inline-end: -0.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 1px solid rgba(226, 232, 240, 0.35);
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.7);
    color: #f8fafc;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
}

.lightbox__close:hover {
    background: rgba(30, 41, 59, 0.9);
}

.lightbox__close:focus-visible {
    outline: 2px solid #ffffff;
    outline-offset: 2px;
}

/* Scroll lock while the lightbox owns the viewport. */
body.lightbox-open {
    overflow: hidden;
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1100px) {
    .gen-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Preview first on narrow screens, but it stops sticking once stacked. */
    .gen-side {
        position: static;
    }

    .hist-grid {
        columns: 3 220px;
    }
}

@media (max-width: 640px) {
    .hist-grid {
        columns: 2;
        column-gap: 0.75rem;
        padding: 0.75rem;
    }

    .hist-card {
        margin-bottom: 0.75rem;
    }

    .hist-card__body {
        padding: 0.5rem 0.6rem 0.6rem;
    }

    .hist-card__prompt {
        font-size: 0.78rem;
    }

    .gen-preview__frame {
        padding: 0.5rem;
    }
}

/* Respect the OS setting: no shimmer, no lift, no slide. */
@media (prefers-reduced-motion: reduce) {
    .gen-preview__shimmer,
    .spinner {
        animation: none;
    }

    .hist-card,
    .hist-card__media img,
    .hist-card__media::after {
        transition: none;
    }

    .hist-card__media::after {
        animation: none;
    }

    .hist-card:hover {
        transform: none;
    }

    .hist-card:hover .hist-card__media img {
        transform: none;
    }
}

/* ==========================================================================
   Nav glyphs — inline SVG replaces the old Unicode blocks, so every icon now
   shares one stroke weight and optical size.
   ========================================================================== */

.sidebar__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.sidebar__glyph,
.empty-state__icon .sidebar__glyph {
    width: 18px;
    height: 18px;
    flex: 0 0 18px;
}

.empty-state__icon {
    display: flex;
    align-items: center;
    justify-content: center;
}

.empty-state__icon .sidebar__glyph {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    color: var(--color-muted);
}

.sidebar-toggle svg {
    width: 20px;
    height: 20px;
}

.sidebar-toggle {
    align-items: center;
    justify-content: center;
}

/* ==========================================================================
   Fitting the page to the device
   ========================================================================== */

/*
   A portrait result (1024x1536) at full column width would be taller than the
   viewport, pushing the Generate button below the fold. Capping the frame
   keeps the whole flow on screen.
*/
.gen-preview__frame {
    max-height: min(72vh, 760px);
}

/* Let the header controls wrap instead of forcing a horizontal scrollbar. */
.content__header .btn-row {
    flex-wrap: wrap;
}

/*
   Short viewports (laptops in landscape, tablets held sideways) cannot fit a
   sticky preview, so it joins the normal flow rather than floating.
*/
@media (max-height: 720px) {
    .gen-side {
        position: static;
    }
}

/* Coarse pointers need a real target, not a 36px desktop-sized one. */
@media (pointer: coarse) {
    .view-toggle__btn {
        min-height: 44px;
        padding-inline: 0.9rem;
    }
}

/* Phone widths: tighten the gutters and let controls use the full width. */
@media (max-width: 560px) {
    .content {
        padding: 0.85rem;
    }

    .content__header {
        gap: 0.75rem;
    }

    /* Stacked columns, so the preview frame must not keep a 340px floor. */
    .gen-layout {
        gap: 1rem;
    }

    .gen-preview__head,
    .gen-preview__foot {
        padding: 0.6rem 0.75rem;
        flex-wrap: wrap;
    }

    .gen-preview__foot a {
        margin-left: 0;
        width: 100%;
        text-align: center;
    }

    .view-toggle {
        width: 100%;
    }

    .view-toggle__btn {
        flex: 1 1 0;
    }

    .card__footer .btn-row {
        flex-direction: column;
        align-items: stretch;
        gap: 0.75rem;
    }

    .card__footer .btn-row .btn {
        width: 100%;
    }

    /* Long prompts must wrap rather than stretch the card. */
    .hist-card__prompt {
        font-size: 0.8rem;
    }
}

/* Very narrow phones keep two compact columns rather than one long strip. */
@media (max-width: 400px) {
    .hist-grid {
        columns: 2;
        column-gap: 0.6rem;
        padding: 0.6rem;
    }

    .hist-card {
        margin-bottom: 0.6rem;
    }

    .form-grid {
        grid-template-columns: 1fr;
    }

/* ==========================================================================
   Compact settings

   The whole point of this section is that every control is reachable without
   scrolling. Size is a row of ratio chips, quality is a dropdown, and the
   image count folds into a single line beside it, which keeps the settings
   card shorter than the preview panel it sits next to.
   ========================================================================== */

.opt-group {
    min-width: 0;
}

.opt-group__label {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.25rem 0.75rem;
    margin-bottom: 0.35rem;
}

.opt-group__label .label {
    margin: 0;
}

/* ------------------------------------------------------ Size: ratios ---- */

/*
   Each chip carries the aspect ratio as its label, with the real pixel
   dimensions underneath. The rectangle previews the shape, so Portrait is
   visibly taller than Landscape without reading the numbers.
*/
.opt-ratios {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
    gap: 0.4rem;
}

.opt-chip {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.4rem 0.55rem;
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.opt-chip:hover {
    border-color: #a5b4fc;
    background: var(--color-primary-soft);
}

.opt-chip__shape {
    --r: 1;
    --shape: 22px;
    flex: 0 0 auto;
    height: var(--shape);
    width: calc(var(--shape) * var(--r));
    min-width: 9px;
    border: 1.5px solid #cbd5e1;
    border-radius: 2px;
    background: #f8fafc;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.opt-chip__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.2;
}

.opt-chip__ratio {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--color-text);
    font-variant-numeric: tabular-nums;
}

.opt-chip__px {
    font-size: 0.66rem;
    color: var(--color-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.opt__input:checked + .opt-chip {
    border-color: var(--color-primary);
    background: var(--color-primary-soft);
}

.opt__input:checked + .opt-chip .opt-chip__shape {
    border-color: var(--color-primary);
    background: #e0e7ff;
}

.opt__input:checked + .opt-chip .opt-chip__ratio {
    font-weight: 700;
    color: var(--color-primary-dark);
}

.opt__input:checked + .opt-chip .opt-chip__px {
    font-weight: 600;
    color: #4338ca;
}

.opt__input:focus-visible + .opt-chip {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* ------------------------------------- Quality + count on one line ----- */

.opt-fields {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 0.6rem;
    align-items: end;
}

.opt-field {
    min-width: 0;
}

/* The dropdown carries its own explanation, so no separate note is needed. */
.select--compact {
    height: 40px;
    padding-block: 0;
}

.opt-fixed {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    height: 40px;
    padding: 0 0.55rem;
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-sm);
    background: #f8fafc;
    font-size: 0.75rem;
    color: var(--color-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.opt-fixed__value {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    min-width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
    font-weight: 700;
    font-size: 0.75rem;
}

/* ---------------------------------------------------------- Prompt box -- */

.prompt-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.3rem;
}

.prompt-counter {
    font-size: 0.72rem;
    color: var(--color-muted);
    font-variant-numeric: tabular-nums;
}

.prompt-counter.is-near {
    color: var(--color-warning);
    font-weight: 600;
}

.prompt-counter.is-over {
    color: var(--color-danger);
    font-weight: 600;
}

.textarea {
    min-height: 5.5rem;
    resize: vertical;
    line-height: 1.5;
}

.seeds {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.4rem;
}

.seed {
    padding: 0.2rem 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-surface);
    color: var(--color-muted);
    font: inherit;
    font-size: 0.7rem;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}

.seed:hover {
    border-color: var(--color-primary);
    color: var(--color-primary-dark);
    background: var(--color-primary-soft);
}

.seed:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* ------------------------------------------------------- Primary CTA ---- */

.btn--cta {
    min-height: 44px;
    padding: 0.6rem 1.75rem;
    font-size: 0.98rem;
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(79, 70, 229, 0.25);
}

.btn--cta:hover:not(:disabled) {
    box-shadow: 0 4px 14px rgba(79, 70, 229, 0.32);
}

.btn--cta:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 3px;
}

.form-cost {
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    min-width: 0;
}

.form-cost__label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-muted);
}

.form-cost__value {
    font-size: 0.95rem;
    color: var(--color-text);
}

/* ---------------------------------------------------------- Responsive -- */

@media (max-width: 720px) {
    .opt-fields {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 400px) {
    .opt-ratios {
        grid-template-columns: repeat(auto-fit, minmax(76px, 1fr));
    }
}

@media (prefers-reduced-motion: reduce) {
    .opt-chip,
    .opt-chip__shape,
    .seed {
        transition: none;
    }
}

/* ==========================================================================
   Lightbox details

   Clicking a gallery image opens it with the record it belongs to, so the
   name and the download action sit under the picture instead of sending the
   user to another page.
   ========================================================================== */

.lightbox__figure {
    width: 100%;
}

/* Reserve room for the details card so it is never pushed off screen. */
.lightbox__figure img {
    max-height: calc(100vh - 15rem);
    max-height: calc(100dvh - 15rem);
}

/*
   A solid light card for the name and actions. Text drawn straight onto the
   dark overlay had no guaranteed contrast and the buttons blended into the
   backdrop; the card fixes both at once.
*/
.lightbox__body {
    display: flex;
    flex-direction: column;
    width: 100%;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--color-surface);
    box-shadow: var(--shadow);
}

.lightbox__body > figcaption {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.75rem 0.9rem 0.9rem;
}

.lightbox__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.lightbox__meta li {
    padding: 0.2rem 0.55rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: #f1f5f9;
    color: var(--color-text);
    font-size: 0.72rem;
    white-space: nowrap;
}

.lightbox__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}

.lightbox__title {
    margin: 0;
    color: var(--color-text);
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.45;
}

.lightbox__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    align-items: center;
}

/* The card is light, so the standard button styles apply untouched. */
.btn--icon {
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 50%;
    flex: 0 0 auto;
}

.btn--icon svg {
    width: 20px;
    height: 20px;
}

/* Icon-only visually, but screen readers still get a real name. */
.lightbox__sr {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* One dot per generated image, filled for the one on screen. */
.lightbox__dots {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    align-items: center;
}

.lightbox__dot {
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: #ffffff;
    color: var(--color-muted);
    font: inherit;
    font-size: 0.7rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}

.lightbox__dot:hover {
    border-color: var(--color-primary);
    color: var(--color-primary-dark);
}

.lightbox__dot[aria-current='true'] {
    border-color: var(--color-primary);
    background: var(--color-primary);
    color: #ffffff;
}

.lightbox__dot:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

@media (max-width: 640px) {
    .lightbox {
        padding: 0.75rem;
    }

    /* The stacked details are taller, so the image gives up more room. */
    .lightbox__figure img {
        max-height: calc(100vh - 17rem);
        max-height: calc(100dvh - 17rem);
    }

    .lightbox__head {
        flex-direction: column;
        gap: 0.6rem;
    }

    .lightbox__actions {
        width: 100%;
    }

    .lightbox__actions .btn--secondary {
        flex: 1 1 auto;
        text-align: center;
    }
}
