/*
 * Design tokens — architecture doc §8: color tokens, a type scale, a spacing
 * scale, defined once here on :root (plus a dark-mode block). No color is
 * ever hardcoded outside this section; every other rule below reads a
 * var(--...) token.
 */
:root {
    /* Color */
    --bg-app: #f1f5f9;
    --bg-primary: #ffffff;
    --bg-secondary: #f8fafc;
    --bg-tertiary: #f1f5f9;
    --bg-hover: #e2e8f0;
    --border-primary: #e2e8f0;
    --border-subtle: #cbd5e1;
    --text-primary: #0f172a;
    --text-secondary: #334155;
    --text-muted: #475569;
    --accent-primary: #2563eb;
    --accent-hover: #1d4ed8;
    --accent-text: #ffffff;
    --accent-subtle-bg: #eff6ff;
    --status-success: #16a34a;
    --status-success-bg: #f0fdf4;
    --status-error: #dc2626;
    --status-error-bg: #fef2f2;
    --status-warning: #d97706;
    --status-warning-bg: #fffbeb;
    --shadow-sm: rgba(0, 0, 0, 0.08);
    --shadow-md: rgba(0, 0, 0, 0.15);
    /* Off-canvas sidebar backdrop (defect 1 — mobile drawer) */
    --overlay-backdrop: rgba(15, 23, 42, 0.5);

    /* Type scale */
    --font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-family-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
    --font-size-xs: 11px;
    --font-size-sm: 12px;
    --font-size-base: 13px;
    --font-size-md: 14px;
    --font-size-lg: 15px;
    --font-size-xl: 17px;
    --font-size-2xl: 20px;
    --line-height-tight: 1.35;
    --line-height-base: 1.5;

    /* Spacing scale */
    --space-1: 4px;
    --space-2: 6px;
    --space-3: 8px;
    --space-4: 10px;
    --space-5: 12px;
    --space-6: 16px;
    --space-7: 20px;
    --space-8: 24px;
    --space-9: 32px;

    /* Radius */
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-full: 999px;

    /* Touch target minimum (defect 1 — no interactive control under ~44px) */
    --tap-target-min: 44px;

    /* Shared header frame height (panel-header-heights defect): the sidebar
       header is naturally the tallest of the three (title row + a "+ New"
       button on its own line), so the other two panel headers grow to match
       it via .panel-header's min-height rather than the sidebar shrinking. */
    --panel-header-height: 92px;
}

[data-theme="dark"] {
    --bg-app: #0b1120;
    --bg-primary: #0f172a;
    --bg-secondary: #1e293b;
    --bg-tertiary: #334155;
    --bg-hover: #334155;
    --border-primary: #334155;
    --border-subtle: #475569;
    --text-primary: #f8fafc;
    --text-secondary: #cbd5e1;
    --text-muted: #94a3b8;
    --accent-primary: #2563eb;
    --accent-hover: #3b82f6;
    --accent-text: #ffffff;
    --accent-subtle-bg: #1e3a8a;
    --status-success: #22c55e;
    --status-success-bg: #14532d;
    --status-error: #ef4444;
    --status-error-bg: #7f1d1d;
    --status-warning: #f59e0b;
    --status-warning-bg: #78350f;
    --shadow-sm: rgba(0, 0, 0, 0.3);
    --shadow-md: rgba(0, 0, 0, 0.5);
    --overlay-backdrop: rgba(0, 0, 0, 0.6);
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    overflow-x: hidden;
}

/* Visibility utility: an inline `style.display` set from JS always wins over
   a stylesheet rule, which would silently defeat a @media rule that later
   tries to change the same element's display at a breakpoint. Controls whose
   shown/hidden state is toggled from app.js use this class instead (see
   app.js for `setHidden`) so the "is it shown" state and the "what display
   value" live in one place, and a breakpoint is always free to restyle the
   shown state. `!important` is deliberate: this class must always win. */
.is-hidden {
    display: none !important;
}

body {
    font-family: var(--font-family-base);
    /* 100vh is wrong on mobile browsers (it ignores the collapsing address
       bar / on-screen keyboard and can hide the composer below the fold).
       100dvh tracks the real visible viewport; the 100vh line above it is
       the fallback for browsers that do not understand dvh. */
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    overflow-x: hidden;
    background-color: var(--bg-app);
    color: var(--text-primary);
    font-size: var(--font-size-md);
}

.icon-svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    stroke: currentColor;
    stroke-width: 2;
    fill: none;
    display: inline-block;
    vertical-align: middle;
}

.app-container {
    display: flex;
    height: 100vh;
    height: 100dvh;
    max-width: 100%;
    overflow-x: hidden;
}

.project-sidebar {
    width: 260px;
    min-width: 260px;
    background: var(--bg-secondary);
    border-right: 1px solid var(--border-primary);
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100dvh;
    transition: width 0.15s ease, min-width 0.15s ease;
    overflow: hidden;
    position: relative;
}

.project-sidebar.collapsed {
    width: 48px;
    min-width: 48px;
}

.project-sidebar.collapsed .project-sidebar-title-row h2,
.project-sidebar.collapsed .new-project-sidebar-btn,
.project-sidebar.collapsed .project-list {
    display: none;
}

.project-sidebar.collapsed .project-sidebar-header {
    padding: var(--space-5) var(--space-3);
    justify-content: center;
}

.project-sidebar.collapsed .project-sidebar-title-row {
    width: 100%;
    justify-content: center;
}

/* Shared frame for the three panel headers (sidebar / chat / preview) — each
   panel keeps its own class and its own contents; this only normalizes the
   outer box (height, horizontal padding, vertical centering) so the three
   read as one consistent row height instead of three independent ones. */
.panel-header {
    min-height: var(--panel-header-height);
    align-items: center;
    box-sizing: border-box;
}

.project-sidebar-header {
    /* Matches .chat-header / .preview-header's own horizontal padding
       exactly (both use --space-5 --space-6) for the shared .panel-header
       frame; each panel's own rule still wins the cascade over
       .panel-header for any property it sets itself, so the padding value
       has to live here rather than only in the shared class. */
    padding: var(--space-5) var(--space-6);
    border-bottom: 1px solid var(--border-primary);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    background: var(--bg-primary);
    flex-shrink: 0;
}

.project-sidebar-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
}

.project-sidebar-title-row h2 {
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
}

.panel-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: var(--space-1);
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.panel-toggle-btn:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
    border-color: var(--border-subtle);
}

.panel-toggle-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.new-project-sidebar-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 7px var(--space-5);
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 500;
    color: var(--accent-text);
    background-color: var(--accent-primary);
    border: 1px solid var(--accent-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
    width: 100%;
}

.new-project-sidebar-btn:hover {
    background-color: var(--accent-hover);
    border-color: var(--accent-hover);
}

.new-project-sidebar-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.project-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--space-5) 10px;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.project-item {
    padding: var(--space-4) var(--space-5);
    background: var(--bg-primary);
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
    user-select: none;
}

.project-item:hover {
    border-color: var(--accent-primary);
    background: var(--accent-subtle-bg);
}

.project-item.active {
    border-color: var(--accent-primary);
    background: var(--accent-subtle-bg);
    box-shadow: 0 0 0 1px var(--accent-primary);
}

.project-item:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.project-item-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.project-item-date {
    font-weight: 500;
}

.project-item-versions {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    padding: 2px var(--space-2);
    border-radius: var(--radius-full);
    font-size: 10px;
    font-weight: 600;
}

.project-item-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.project-item-rename-btn,
.project-item-delete-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: var(--font-size-sm);
    padding: 3px 5px;
    border-radius: var(--radius-sm);
    line-height: 1;
    transition: color 0.15s, background-color 0.15s, border-color 0.15s;
}

.project-item-rename-btn:hover {
    color: var(--accent-primary);
    background-color: var(--bg-hover);
    border-color: var(--border-subtle);
}

.project-item-rename-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.project-item-delete-btn:hover {
    color: var(--status-error);
    background-color: var(--status-error-bg);
    border-color: var(--status-error);
}

.project-item-delete-btn:focus-visible {
    outline: 2px solid var(--status-error);
    outline-offset: 1px;
}

.project-item-delete-btn:disabled,
.project-item-rename-btn:disabled {
    opacity: 0.5;
    cursor: wait;
}

.project-item-name {
    font-size: var(--font-size-base);
    color: var(--text-primary);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: var(--line-height-tight);
}

.project-inline-edit-input {
    width: 100%;
    font-size: var(--font-size-base);
    padding: 3px var(--space-2);
    background: var(--bg-primary);
    color: var(--text-primary);
    border: 1px solid var(--accent-primary);
    border-radius: var(--radius-sm);
    outline: none;
    box-sizing: border-box;
    font-family: inherit;
}

.project-inline-edit-input:disabled {
    opacity: 0.6;
    cursor: wait;
}

/* Empty / loading / error states — shared by any list in the app. */
.list-empty-state,
.list-loading-state {
    text-align: center;
    color: var(--text-muted);
    font-size: var(--font-size-base);
    padding: 30px var(--space-4);
    font-style: italic;
}

.list-error-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    text-align: center;
    color: var(--status-error);
    background: var(--status-error-bg);
    border: 1px solid var(--status-error);
    border-radius: var(--radius-md);
    padding: var(--space-5);
    font-size: var(--font-size-base);
}

.list-error-retry-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-2) var(--space-5);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 500;
    color: var(--status-error);
    background: var(--bg-primary);
    border: 1px solid var(--status-error);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.list-error-retry-btn:hover {
    background: var(--status-error-bg);
}

.list-error-retry-btn:focus-visible {
    outline: 2px solid var(--status-error);
    outline-offset: 1px;
}

.chat-panel {
    width: 35%;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--border-primary);
    background: var(--bg-secondary);
    flex-shrink: 0;
    transition: width 0.15s ease, min-width 0.15s ease;
}

/* Panel-level collapse (defect 3) — consistent with the sidebar: the WHOLE
   chat panel becomes a narrow rail, not just its header strip, so its space
   is actually handed back to the preview panel (flex: 1 on .preview-panel
   absorbs it automatically). #headerToggleBtn stays visible on the rail as
   the reopen control, mirroring #sidebarToggleBtn. */
.chat-panel.collapsed {
    width: 48px;
    min-width: 48px;
    flex: 0 0 48px;
}

.chat-panel.collapsed .chat-header-title-container,
.chat-panel.collapsed .chat-header-actions > *:not(.header-toggle-btn),
.chat-panel.collapsed .chat-messages,
.chat-panel.collapsed .chat-input-area {
    display: none;
}

.chat-panel.collapsed .chat-header {
    justify-content: center;
    padding: var(--space-5) var(--space-3);
}

.chat-header {
    padding: var(--space-5) var(--space-6);
    border-bottom: 1px solid var(--border-primary);
    background: var(--bg-primary);
    display: flex;
    flex-wrap: wrap;
    row-gap: var(--space-3);
    justify-content: space-between;
    align-items: center;
    gap: var(--space-3);
    transition: padding 0.15s ease, min-height 0.15s ease;
    flex-shrink: 0;
}

/* defect 2 — never let the header's own controls shrink below their natural
   (>= 44px) size; wrap onto a second line instead of squeezing/overlapping. */
.chat-header-actions > * {
    flex-shrink: 0;
}

.chat-header h1 {
    font-size: var(--font-size-xl);
    color: var(--text-primary);
}

.chat-header-title-container {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.active-project-name-wrapper {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.active-project-title {
    font-size: var(--font-size-base);
    color: var(--text-muted);
    font-weight: 500;
    cursor: pointer;
    border-bottom: 1px dashed var(--border-subtle);
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.active-project-title:hover {
    color: var(--accent-primary);
    border-bottom-color: var(--accent-primary);
}

.active-project-title-input {
    font-size: var(--font-size-base);
    padding: 2px var(--space-2);
    background: var(--bg-primary);
    color: var(--text-primary);
    border: 1px solid var(--accent-primary);
    border-radius: var(--radius-sm);
    outline: none;
    font-family: inherit;
    max-width: 240px;
}

.edit-project-title-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: var(--font-size-sm);
    padding: 3px 5px;
    border-radius: var(--radius-sm);
    line-height: 1;
    transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}

.edit-project-title-btn:hover {
    color: var(--accent-primary);
    background-color: var(--bg-hover);
    border-color: var(--border-subtle);
}

.edit-project-title-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.chat-header-actions {
    display: flex;
    flex-wrap: wrap;
    row-gap: var(--space-3);
    align-items: center;
    gap: var(--space-3);
}

.theme-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-3) var(--space-4);
    font-family: inherit;
    font-size: var(--font-size-base);
    line-height: 1;
    background: var(--bg-tertiary);
    color: var(--text-primary);
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
    user-select: none;
}

.theme-toggle-btn:hover {
    background: var(--bg-hover);
    border-color: var(--border-subtle);
}

.theme-toggle-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.new-project-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 500;
    color: var(--text-secondary);
    background-color: var(--bg-tertiary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.new-project-button:hover {
    background-color: var(--bg-hover);
    color: var(--text-primary);
    border-color: var(--border-primary);
}

.new-project-button:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.logout-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 500;
    color: var(--text-muted);
    background-color: transparent;
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.logout-button:hover {
    background-color: var(--status-error-bg);
    color: var(--status-error);
    border-color: var(--status-error);
}

.logout-button:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.logout-button:disabled {
    opacity: 0.6;
    cursor: wait;
}

.chat-messages {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--space-6);
}

.chat-messages[aria-busy="true"] {
    opacity: 0.6;
}

.empty-state {
    text-align: center;
    color: var(--text-muted);
    padding: 40px var(--space-7);
    font-style: italic;
}

.message {
    margin-bottom: var(--space-5);
    padding: var(--space-4) 14px;
    border-radius: var(--radius-md);
    max-width: 90%;
    word-wrap: break-word;
}

.message.user {
    background: var(--accent-primary);
    color: var(--accent-text);
    margin-left: auto;
    text-align: right;
}

.message.assistant {
    background: var(--bg-primary);
    color: var(--text-primary);
    border: 1px solid var(--border-primary);
}

.message.error {
    background: var(--status-error-bg);
    color: var(--status-error);
    border: 1px solid var(--status-error);
}

.message.typing {
    color: var(--text-muted);
    font-style: italic;
}

.version-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-3);
    padding: var(--space-1) 10px;
    background-color: var(--accent-subtle-bg);
    color: var(--accent-primary);
    border: 1px solid var(--accent-primary);
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
    text-decoration: none;
}

.version-badge:hover {
    background-color: var(--bg-hover);
}

.version-badge:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.chat-input-area {
    padding: var(--space-6);
    border-top: 1px solid var(--border-primary);
    background: var(--bg-primary);
    display: flex;
    gap: var(--space-3);
}

.chat-input-area textarea {
    flex: 1;
    padding: var(--space-4);
    background: var(--bg-secondary);
    color: var(--text-primary);
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-sm);
    resize: none;
    font-family: inherit;
    font-size: var(--font-size-md);
}

.chat-input-area textarea:focus-visible {
    outline: 2px solid var(--accent-primary);
    border-color: var(--accent-primary);
}

.send-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-8);
    background: var(--accent-primary);
    color: var(--accent-text);
    border: 1px solid var(--accent-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--font-size-md);
    font-weight: 500;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.send-button:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

/* While a generation is in flight the send button becomes a cancel button
   (10.7's explicit-cancel trigger) rather than a disabled dead end. */
.send-button.is-cancel {
    background: var(--status-error-bg);
    color: var(--status-error);
    border-color: var(--status-error);
}

.send-button.is-cancel:hover {
    background: var(--status-error);
    color: var(--accent-text);
}

.send-button:disabled {
    background: var(--bg-tertiary);
    color: var(--text-muted);
    border-color: var(--border-primary);
    cursor: not-allowed;
}

.send-button:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.preview-panel {
    width: 60%;
    flex: 1;
    display: flex;
    flex-direction: column;
    background: var(--bg-app);
}

.preview-header {
    padding: var(--space-5) var(--space-6);
    border-bottom: 1px solid var(--border-primary);
    background: var(--bg-primary);
    display: flex;
    flex-wrap: wrap;
    row-gap: var(--space-3);
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
}

.preview-header h2 {
    font-size: var(--font-size-xl);
    color: var(--text-primary);
    flex-shrink: 0;
}

.preview-header-left {
    display: flex;
    flex-wrap: wrap;
    row-gap: var(--space-3);
    align-items: center;
    gap: var(--space-5);
}

.preview-tabs {
    display: flex;
    align-items: center;
    background-color: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    padding: 2px;
    gap: 2px;
}

.tab-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 5px var(--space-5);
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 500;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.tab-button:hover {
    color: var(--text-primary);
}

.tab-button.active {
    background: var(--bg-primary);
    color: var(--accent-primary);
    border-color: var(--border-primary);
    box-shadow: 0 1px 3px var(--shadow-sm);
}

.tab-button:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.preview-header-right {
    display: flex;
    flex-wrap: wrap;
    row-gap: var(--space-3);
    align-items: center;
    gap: var(--space-3);
}

/* defect 2 — never let these clusters shrink their controls below the
   ~44px touch minimum; wrap onto another line instead of squeezing/
   overlapping them. */
.preview-header-left > *,
.preview-header-right > * {
    flex-shrink: 0;
}

.viewport-controls {
    display: flex;
    align-items: center;
    background-color: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    padding: 2px;
    gap: 2px;
}

.viewport-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 5px var(--space-4);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 500;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.viewport-button:hover {
    color: var(--text-primary);
}

.viewport-button.active {
    background: var(--bg-primary);
    color: var(--accent-primary);
    border-color: var(--border-primary);
    box-shadow: 0 1px 3px var(--shadow-sm);
}

.viewport-button:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.copy-link-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    background: var(--accent-primary);
    color: var(--accent-text);
    border: 1px solid var(--accent-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 500;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.copy-link-btn:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

.copy-link-btn.copied {
    background: var(--status-success);
    border-color: var(--status-success);
}

.copy-link-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.copy-code-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    background: var(--bg-tertiary);
    color: var(--text-primary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 500;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.copy-code-button:hover {
    background: var(--bg-hover);
    border-color: var(--border-primary);
}

.copy-code-button.copied {
    background: var(--status-success);
    border-color: var(--status-success);
    color: var(--accent-text);
}

.copy-code-button:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.version-selector-container {
    display: flex;
    align-items: center;
}

.version-select {
    display: block;
    padding: var(--space-3) var(--space-5);
    font-size: var(--font-size-base);
    font-weight: 500;
    font-family: inherit;
    color: var(--text-primary);
    background-color: var(--bg-secondary);
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.version-select:focus-visible {
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 2px var(--accent-subtle-bg);
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.download-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) 14px;
    background: var(--status-success);
    color: var(--accent-text);
    border: 1px solid var(--status-success);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 500;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.download-button:hover {
    background: var(--status-success);
    filter: brightness(1.05);
}

.download-button:disabled {
    opacity: 0.6;
    cursor: wait;
}

.download-button:focus-visible {
    outline: 2px solid var(--status-success);
    outline-offset: 1px;
}

.preview-container {
    flex: 1;
    min-height: 0;
    padding: var(--space-6);
    background: var(--bg-app);
    display: flex;
    justify-content: center;
    overflow: hidden;
}

.preview-frame-container {
    display: flex;
    height: 100%;
    transition: width 0.15s ease, max-width 0.15s ease;
    justify-content: center;
    position: relative;
}

.preview-loading-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: var(--bg-primary);
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-sm);
    padding: var(--space-9) var(--space-8);
    box-sizing: border-box;
    text-align: center;
    gap: var(--space-6);
}

.preview-loading-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid var(--border-primary);
    border-top-color: var(--accent-primary);
    border-radius: 50%;
    animation: preview-spin 0.8s linear infinite;
}

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

.preview-loading-text-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
}

.preview-loading-title {
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
}

.preview-loading-progress {
    font-size: var(--font-size-base);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    margin: 0;
}

/* Indeterminate bar: generation is a single call, not a stream, so there is
   no real percentage to show. It is paired with the rotating status
   messages above. */
.preview-loading-bar {
    width: 220px;
    max-width: 70%;
    height: 4px;
    border-radius: var(--radius-full);
    background: var(--border-primary);
    overflow: hidden;
}

.preview-loading-bar-fill {
    display: block;
    width: 40%;
    height: 100%;
    border-radius: var(--radius-full);
    background: var(--accent-primary);
    animation: preview-loading-slide 1.4s ease-in-out infinite;
}

@keyframes preview-loading-slide {
    0% { transform: translateX(-120%); }
    100% { transform: translateX(340%); }
}

@media (prefers-reduced-motion: reduce) {
    .preview-loading-bar-fill {
        animation-duration: 3s;
    }
}

.preview-frame-container.viewport-desktop {
    width: 100%;
    max-width: 100%;
}

.preview-frame-container.viewport-mobile {
    /* min() instead of a bare 375px: the "Mobile" viewport-simulator mode
       must not force horizontal scroll when the preview panel itself is
       narrower than 375px (defect 1 — this app must also work at ~360px). */
    width: min(375px, 100%);
    max-width: 100%;
    margin: 0 auto;
    box-shadow: 0 4px 16px var(--shadow-md);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.preview-iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-sm);
    background: var(--bg-primary);
}

.code-container {
    width: 100%;
    height: 100%;
    background: var(--bg-secondary);
    border-radius: var(--radius-sm);
    overflow: auto;
    border: 1px solid var(--border-primary);
}

.source-code-pre {
    margin: 0;
    padding: var(--space-6);
    height: 100%;
    box-sizing: border-box;
    overflow: auto;
}

.source-code-content {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-base);
    line-height: var(--line-height-base);
    color: var(--text-primary);
    white-space: pre-wrap;
    word-break: break-all;
}

/* Login page */
.login-body {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background-color: var(--bg-app);
    color: var(--text-primary);
}

.login-wrapper {
    width: 100%;
    max-width: 420px;
    padding: var(--space-8);
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

.login-header {
    display: flex;
    justify-content: flex-end;
}

.login-card {
    background: var(--bg-primary);
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-md);
    padding: var(--space-9) 28px;
    box-shadow: 0 4px 16px var(--shadow-md);
}

.login-card-header {
    text-align: center;
    margin-bottom: var(--space-8);
}

.login-icon-container {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    background: var(--accent-subtle-bg);
    color: var(--accent-primary);
    border-radius: 50%;
    margin-bottom: var(--space-6);
}

.login-key-icon {
    width: 28px;
    height: 28px;
}

.login-card-header h1 {
    font-size: var(--font-size-2xl);
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: var(--space-3);
}

.login-subtitle {
    font-size: var(--font-size-base);
    color: var(--text-muted);
    line-height: 1.4;
}

.login-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-7);
}

.login-form-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.login-label {
    font-size: var(--font-size-base);
    font-weight: 500;
    color: var(--text-secondary);
}

.password-input-wrapper {
    position: relative;
    display: flex;
    align-items: center;
}

.login-input {
    width: 100%;
    padding: var(--space-4) 42px var(--space-4) var(--space-5);
    background: var(--bg-secondary);
    color: var(--text-primary);
    border: 1px solid var(--border-primary);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-md);
    font-family: inherit;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.login-input:focus-visible {
    border-color: var(--accent-primary);
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.login-input:disabled {
    background: var(--bg-tertiary);
    color: var(--text-muted);
    cursor: not-allowed;
}

.password-toggle-btn {
    position: absolute;
    right: var(--space-3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-muted);
    padding: var(--space-1);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: color 0.15s ease, background-color 0.15s ease;
}

.password-toggle-btn:hover {
    color: var(--text-primary);
    background-color: var(--bg-hover);
}

.password-toggle-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.login-feedback {
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-base);
    line-height: 1.4;
    background-color: var(--status-error-bg);
    color: var(--status-error);
    border: 1px solid var(--status-error);
}

.login-feedback.warning {
    background-color: var(--status-warning-bg);
    color: var(--status-warning);
    border-color: var(--status-warning);
}

.login-submit-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    width: 100%;
    padding: var(--space-4) var(--space-6);
    background-color: var(--accent-primary);
    color: var(--accent-text);
    border: 1px solid var(--accent-primary);
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: var(--font-size-md);
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.login-submit-btn:hover {
    background-color: var(--accent-hover);
    border-color: var(--accent-hover);
}

.login-submit-btn:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 1px;
}

.login-submit-btn:disabled {
    background-color: var(--bg-tertiary);
    color: var(--text-muted);
    border-color: var(--border-primary);
    cursor: not-allowed;
}

/* ===========================================================================
 * Responsive pass (defect 1 — narrow viewports, down to ~360px)
 *
 * Additive only: everything above this line is the desktop layout, unchanged.
 * Two breakpoints:
 *
 *   1. max-width: 860px  — layout collapse. The sidebar becomes an off-canvas
 *      drawer; the chat and preview panels can no longer sit side by side, so
 *      only one is shown at a time behind a segmented "Conversation / Preview"
 *      switch; a mobile top bar carries the drawer opener and that switch;
 *      every interactive control is bumped to the ~44px touch minimum.
 *   2. max-width: 480px  — compact spacing. Padding/gaps are tightened so the
 *      layout is comfortable (not just non-overflowing) down to ~360px.
 *
 * No new colors are introduced outside the :root / [data-theme="dark"] token
 * blocks above — every rule below reads var(--...) tokens only.
 * ========================================================================= */

.mobile-nav-bar {
    display: none;
}

.sidebar-backdrop {
    display: none;
}

@media (max-width: 860px) {
    /* --- Touch targets: no interactive control smaller than ~44px --- */
    button,
    select,
    input[type="text"] {
        min-height: var(--tap-target-min);
    }

    .panel-toggle-btn,
    .project-item-rename-btn,
    .project-item-delete-btn,
    .edit-project-title-btn,
    .mobile-sidebar-toggle-btn,
    .password-toggle-btn {
        min-width: var(--tap-target-min);
    }

    /* --- Mobile top bar --- */
    .mobile-nav-bar {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--space-3);
        padding: var(--space-3) var(--space-4);
        background: var(--bg-primary);
        border-bottom: 1px solid var(--border-primary);
        flex-shrink: 0;
    }

    .mobile-sidebar-toggle-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: transparent;
        color: var(--text-secondary);
        border: 1px solid var(--border-primary);
        border-radius: var(--radius-sm);
        cursor: pointer;
    }

    .mobile-sidebar-toggle-btn:hover {
        background: var(--bg-hover);
        color: var(--text-primary);
    }

    .mobile-sidebar-toggle-btn:focus-visible {
        outline: 2px solid var(--accent-primary);
        outline-offset: 1px;
    }

    .mobile-view-switch {
        display: flex;
        align-items: center;
        flex: 1;
        background-color: var(--bg-tertiary);
        border-radius: var(--radius-sm);
        padding: 2px;
        gap: 2px;
    }

    .mobile-view-btn {
        flex: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-family: inherit;
        font-size: var(--font-size-base);
        font-weight: 500;
        color: var(--text-secondary);
        background: transparent;
        border: 1px solid transparent;
        border-radius: var(--radius-sm);
        cursor: pointer;
        transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
    }

    .mobile-view-btn.active {
        background: var(--bg-primary);
        color: var(--accent-primary);
        border-color: var(--border-primary);
        box-shadow: 0 1px 3px var(--shadow-sm);
    }

    .mobile-view-btn:focus-visible {
        outline: 2px solid var(--accent-primary);
        outline-offset: 1px;
    }

    /* --- Sidebar becomes an off-canvas drawer ---
       The desktop rail-collapse control (sidebarToggleBtn) stays in the DOM
       and now doubles as the drawer's close button, visible once the drawer
       is open; the mobile-only hamburger above is the opener. Neither traps
       focus: both are ordinary buttons and Tab can leave the drawer freely. */
    .project-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 100;
        width: min(85vw, 320px);
        min-width: 0;
        max-width: 320px;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: 4px 0 24px var(--shadow-md);
    }

    .project-sidebar.collapsed {
        /* The desktop "rail" state means nothing off-canvas; neutralize it. */
        width: min(85vw, 320px);
        min-width: 0;
    }

    .project-sidebar.collapsed .project-sidebar-title-row h2 {
        display: block;
    }

    .project-sidebar.collapsed .new-project-sidebar-btn {
        display: inline-flex;
    }

    .project-sidebar.collapsed .project-list {
        display: flex;
    }

    .project-sidebar.collapsed .project-sidebar-header {
        padding: var(--space-5) 14px;
        justify-content: flex-start;
    }

    .project-sidebar.collapsed .project-sidebar-title-row {
        justify-content: space-between;
    }

    .project-sidebar.mobile-open {
        transform: translateX(0);
    }

    .sidebar-backdrop:not([hidden]) {
        display: block;
        position: fixed;
        inset: 0;
        background: var(--overlay-backdrop);
        z-index: 90;
    }

    /* --- Chat and preview stack instead of sitting side by side --- */
    .app-container {
        flex-direction: column;
    }

    .chat-panel,
    .preview-panel {
        width: 100%;
        flex: 1 1 auto;
        min-height: 0;
        border-right: none;
    }

    .preview-panel {
        display: none;
    }

    .app-container.mobile-view-preview .chat-panel {
        display: none;
    }

    .app-container.mobile-view-preview .preview-panel {
        display: flex;
    }

    /* The desktop rail-collapse (defect 3) is a desktop-only affordance: on
       mobile, showing/hiding the chat panel is already the job of the
       Conversation/Preview switch above, so neutralize .collapsed here
       exactly like the sidebar's .collapsed rail is neutralized above. */
    .chat-panel.collapsed {
        width: 100%;
        min-width: 0;
        flex: 1 1 auto;
    }

    .chat-panel.collapsed .chat-header-title-container {
        display: flex;
    }

    .chat-panel.collapsed .chat-header-actions > * {
        display: inline-flex;
    }

    .chat-panel.collapsed .chat-messages {
        display: block;
    }

    .chat-panel.collapsed .chat-input-area {
        display: flex;
    }

    .chat-panel.collapsed .chat-header {
        justify-content: space-between;
        padding: var(--space-4);
    }
}

@media (max-width: 480px) {
    /* --- Compact spacing down to ~360px --- */
    /* (flex-wrap itself is unconditional now — see defect 2 fix above — this
       breakpoint only tightens the padding further.) */
    .chat-header,
    .preview-header {
        padding: var(--space-4);
    }

    .chat-messages,
    .preview-container {
        padding: var(--space-4);
    }

    .chat-input-area {
        padding: var(--space-4);
    }

    .mobile-nav-bar {
        padding: var(--space-2) var(--space-3);
    }

    .project-sidebar {
        width: min(90vw, 300px);
    }

    .preview-header-left,
    .preview-header-right {
        gap: var(--space-3);
    }

    .active-project-title,
    .active-project-title-input {
        max-width: 140px;
    }
}

/* ---------------------------------------------------------------------------
   Compact panel-header controls
   ---------------------------------------------------------------------------
   Reported from the running app: the three panel headers still look different
   because their control rows wrap onto a second line at ordinary desktop
   widths, and a wrapped row is taller than an unwrapped one.

   Wrapping was added deliberately to stop the controls overlapping, and it
   stays -- it is the safety net at narrow widths. What was missing is making
   the controls small enough that the net is never needed on a desktop. So the
   fix is to shrink the controls, not to forbid the wrap: removing
   `flex-wrap` would bring the overlap straight back.

   Every value below is a token. Touch targets are restored to 44px in the
   mobile query further down, where a finger is the pointer.
--------------------------------------------------------------------------- */

:root {
    /* One unwrapped row of compact controls plus the title line. Was 92px,
       which was sized to fit two wrapped rows. */
    --panel-header-height: 68px;
    --header-control-padding-y: 5px;
    --header-control-padding-x: var(--space-4);
    --header-control-font-size: var(--font-size-sm);
    --header-control-gap: var(--space-2);
}

.chat-header-actions,
.preview-header-left,
.preview-header-right {
    gap: var(--header-control-gap);
    column-gap: var(--header-control-gap);
}

.chat-header-actions .new-project-button,
.chat-header-actions .logout-button,
.chat-header-actions .theme-toggle-btn,
.preview-header-right .viewport-button,
.preview-header-left .tab-button {
    padding: var(--header-control-padding-y) var(--header-control-padding-x);
    font-size: var(--header-control-font-size);
    gap: var(--space-1, 4px);
    white-space: nowrap;
}

/* The icons carried the same size as body text and pushed each control wider
   than its label needed. */
.chat-header-actions .icon-svg,
.preview-header-right .icon-svg,
.preview-header-left .icon-svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

.preview-header-left .version-select {
    padding: var(--header-control-padding-y) var(--header-control-padding-x);
    font-size: var(--header-control-font-size);
}

/* A finger is not a mouse: restore comfortable targets where the layout has
   already stacked into the mobile arrangement. */
@media (max-width: 860px) {
    .chat-header-actions .new-project-button,
    .chat-header-actions .logout-button,
    .chat-header-actions .theme-toggle-btn,
    .preview-header-right .viewport-button,
    .preview-header-left .tab-button,
    .preview-header-left .version-select {
        min-height: 44px;
        padding: var(--space-2) var(--space-4);
        font-size: var(--font-size-base);
    }

    .chat-header-actions .icon-svg,
    .preview-header-right .icon-svg,
    .preview-header-left .icon-svg {
        width: 16px;
        height: 16px;
    }
}

/* ---------------------------------------------------------------------------
   One row, one height, three headers
   ---------------------------------------------------------------------------
   Measured in the browser rather than guessed: with only a `min-height` the
   three headers came out 95px, 111px and 99px. The min-height was never the
   constraint -- each header's own children were stacking, because a title and
   a control cluster would not fit side by side and the header wrapped them:

     .chat-header      title block (50px, two lines) above actions (28px)
     .preview-header   left cluster (31px) above right cluster (35px)
     .sidebar-header   title row above a full-width call to action

   So the fix is to make the content fit one row, and only then fix the height.
   `height` rather than `min-height`, because a minimum is exactly what the
   content was already overrunning.

   The sidebar's "+ New" moved OUT of the header in the markup: it is a
   full-width call to action, not a header control, and asking it to sit on a
   title row would have shrunk it for no reason. It keeps its id and its place
   on screen.
--------------------------------------------------------------------------- */

:root {
    --panel-header-height: 56px;
}

.panel-header {
    height: var(--panel-header-height);
    min-height: var(--panel-header-height);
    flex-wrap: nowrap;
    align-items: center;
    overflow: hidden;
}

/* The sidebar header is now just its title row. */
.project-sidebar-header {
    flex-direction: row;
}

.project-sidebar-title-row {
    flex: 1 1 auto;
    min-width: 0;
}

/* Title and project name side by side instead of stacked. `min-width: 0` is
   what lets a flex child actually shrink -- without it the name refuses to
   truncate and pushes the controls onto a second row, which is how this
   header reached 111px. */
.chat-header-title-container {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    gap: var(--space-3);
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
}

.chat-header-title-container h1 {
    flex: 0 0 auto;
    white-space: nowrap;
}

.active-project-name-wrapper {
    min-width: 0;
    overflow: hidden;
}

.active-project-title {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

.chat-header-actions,
.preview-header-right {
    flex: 0 0 auto;
}

.preview-header-left {
    flex: 1 1 auto;
    min-width: 0;
}

/* Narrow screens keep the safety net: there, wrapping is the correct answer
   and a taller header is better than overlapping controls. */
@media (max-width: 860px) {
    .panel-header {
        height: auto;
        min-height: var(--panel-header-height);
        flex-wrap: wrap;
        overflow: visible;
    }

    .chat-header-title-container {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-1);
    }
}

/* ---------------------------------------------------------------------------
   Never clip a control
   ---------------------------------------------------------------------------
   Regression from the fixed-height header above, caught by the operator and
   then measured: the preview panel is 536px wide, its right cluster is 504px
   and does not shrink, so the left cluster was squeezed to ONE pixel and its
   children -- the version selector and the Preview/Code tabs -- overflowed and
   were hidden by `overflow: hidden`.

   A clipped control is worse than an ugly one: it is invisible AND
   unclickable, and nothing on screen says it exists. `overflow: hidden` on a
   fixed-height bar is a trap for exactly this reason, so it is gone.

   The controls genuinely did not fit -- roughly 780px of content in 536px --
   so the fix is to make them narrower rather than to pretend. Below a panel
   width where the labels stop fitting, the action buttons become icon-only
   (their aria-label and title still say what they do) and the redundant
   "Preview" heading is dropped: the panel is self-evidently the preview.
--------------------------------------------------------------------------- */

.preview-panel,
.chat-panel {
    container-type: inline-size;
}

.panel-header {
    overflow: visible;
}

/* Inside the left cluster only the heading may shrink. The version selector
   and the tabs are how the user reaches other versions and the source, so
   they hold their size. */
.preview-header-left > h2 {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.preview-header-left .version-selector-container,
.preview-header-left .preview-tabs,
.preview-header-right .viewport-controls,
.preview-header-right > button {
    flex: 0 0 auto;
}

@container (max-width: 760px) {
    .preview-header-right .copy-link-btn span,
    .preview-header-right .copy-code-button span,
    .preview-header-right .download-button span {
        display: none;
    }

    .preview-header-right .copy-link-btn,
    .preview-header-right .copy-code-button,
    .preview-header-right .download-button {
        padding-inline: var(--space-2);
    }
}

@container (max-width: 620px) {
    /* The heading is the first thing to go: the panel is obviously the
       preview, and the controls are not obvious at all. */
    .preview-header-left > h2 {
        display: none;
    }

    .preview-header-right .viewport-button span {
        display: none;
    }

    .preview-header-right .viewport-button {
        padding-inline: var(--space-2);
    }
}

/* The chat header gets the same treatment, for the same reason: at 429px its
   panel was below the wrap threshold, so it grew to 60px while the other two
   stayed at 56 and the headers stopped matching again. Shrinking the controls
   keeps it on one row instead. */
@container (max-width: 720px) {
    .chat-header-actions .new-project-button span,
    .chat-header-actions .logout-button span {
        display: none;
    }

    .chat-header-actions .new-project-button,
    .chat-header-actions .logout-button {
        padding-inline: var(--space-2);
    }
}

@container (max-width: 560px) {
    /* The application's own name inside the application is the least useful
       text on this row; the project name it is showing is the useful one. */
    .chat-header-title-container h1 {
        display: none;
    }
}

@container (max-width: 380px) {
    /* Past here nothing sensible fits on one line. Wrapping is the honest
       answer -- a taller header beats a control you cannot reach. */
    .panel-header {
        height: auto;
        flex-wrap: wrap;
        row-gap: var(--space-2);
        padding-block: var(--space-2);
    }
}
