Spaces:
Runtime error
Runtime error
File size: 9,421 Bytes
d44ff09 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /* ============================================================================
App shell + screen layout (Section 2.0 global nav, 2.1β2.5 screens).
MOBILE-FIRST responsive system: base styles target the smallest screens,
then min-width breakpoints progressively enhance toward desktop.
Covers: phones (320-480px), tablets (768-1024px), laptops, wide desktops.
========================================================================== */
/* ===== Base (mobile-first): designed for 320px+ ===== */
* { -webkit-tap-highlight-color: transparent; }
html { -webkit-text-size-adjust: 100%; }
.app-shell { display: flex; min-height: 100vh; min-height: 100dvh; /* dynamic viewport: accounts for mobile browser chrome */ }
/* Sidebar: drawer by default (mobile), persistent on >= md */
.sidebar {
width: min(280px, 84vw); background: var(--color-surface); border-right: 1px solid var(--color-border);
padding: var(--space-6) var(--space-4); display: flex; flex-direction: column; gap: var(--space-2);
flex-shrink: 0; height: 100vh; height: 100dvh;
/* mobile drawer state */
position: fixed; left: 0; top: 0; z-index: 900; transform: translateX(-100%);
transition: transform .25s ease; box-shadow: 2px 0 16px rgba(0,0,0,.18); overflow-y: auto;
}
.sidebar.open { transform: translateX(0); }
.sidebar .logo { font-size: var(--fs-fluid-md); font-weight: 800; color: var(--color-primary); margin-bottom: var(--space-6); display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.nav-link { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); border-radius: var(--radius); color: var(--color-text-secondary); text-decoration: none; font-size: var(--fs-14); font-weight: 600; min-height: 44px; /* touch target a11y */ }
.nav-link:hover { background: var(--color-surface-muted); color: var(--color-text-primary); }
.nav-link.active { background: rgba(13,125,107,.1); color: var(--color-primary); }
.sidebar .spacer { flex: 1; }
.main {
flex: 1; padding: var(--space-4); width: 100%; min-width: 0;
max-width: 1200px; margin: 0 auto;
}
.page-title { font-size: var(--fs-fluid-xl); margin-bottom: var(--space-2); line-height: 1.15; word-break: break-word; }
.page-sub { color: var(--color-text-secondary); margin-bottom: var(--space-6); font-size: var(--fs-fluid-sm); }
/* Mobile menu button: visible by default */
.menu-toggle { display: inline-flex; }
.scrim { display: none; }
.scrim.show { display: block; position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 800; }
/* Auth screen */
.auth-wrap { min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: var(--space-4); }
.auth-card { width: 100%; max-width: 420px; }
/* Dashboard widgets */
.stat-card { display: flex; flex-direction: column; gap: var(--space-1); }
.stat-card .num { font-size: var(--fs-fluid-2xl); font-weight: 800; color: var(--color-primary); line-height: 1; }
/* Editor: single column by default (mobile), dual-pane on >= md */
.editor-wrap { display: grid; grid-template-columns: 1fr; gap: var(--space-5); }
.editor-pane { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.preview-frame { border: 1px solid var(--color-border); border-radius: var(--radius); padding: var(--space-4); background: var(--color-on-primary); min-height: 300px; overflow: auto; max-height: 70vh; /* review HTML can wrap */ word-break: break-word; }
.json-preview { font-family: var(--font-mono); font-size: var(--fs-12); background: var(--color-code-bg); color: var(--color-code-fg); padding: var(--space-3); border-radius: var(--radius); white-space: pre-wrap; word-break: break-word; max-height: 70vh; overflow: auto; }
.code-editor { font-family: var(--font-mono); font-size: var(--fs-12); min-height: 260px; }
/* Tables: horizontally scrollable wrapper on small screens */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.tbl { width: 100%; border-collapse: collapse; min-width: 560px; /* keeps columns usable inside scroll */ }
table.tbl th, table.tbl td { text-align: left; padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-border); font-size: var(--fs-14); white-space: nowrap; }
table.tbl td:first-child { white-space: normal; }
/* Export screen */
.export-row { display: grid; grid-template-columns: 1fr; gap: var(--space-2); padding: var(--space-4) 0; border-bottom: 1px solid var(--color-border); }
/* Progress bar */
.progress { height: 8px; background: var(--color-surface-muted); border-radius: 999px; overflow: hidden; }
.progress > div { height: 100%; background: var(--color-primary); transition: width .3s; }
.error-banner { background: var(--color-banner-error-bg); border: 1px solid var(--color-banner-error-border); color: var(--color-banner-error-fg); padding: var(--space-3) var(--space-4); border-radius: var(--radius); font-size: var(--fs-fluid-sm); display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.empty-state { text-align: center; padding: var(--space-8) var(--space-4); color: var(--color-text-secondary); }
.empty-state .ill { font-size: 48px; margin-bottom: var(--space-4); }
.pagination { display: flex; gap: var(--space-2); justify-content: center; align-items: center; margin-top: var(--space-6); flex-wrap: wrap; }
/* Row components stack vertically by default */
.row { display: flex; gap: var(--space-4); flex-wrap: wrap; }
.grid { display: grid; gap: var(--space-4); }
/* Responsive auto-fit grid β collapses columns based on available width
without needing breakpoints (used for stat cards, checkbox groups). */
.grid-auto { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
/* Two-column grid that collapses to one column under the tablet breakpoint. */
.grid-2 { display: grid; gap: var(--space-4); grid-template-columns: 1fr; }
@media (min-width: 480px) { .grid-2 { grid-template-columns: 1fr 1fr; } }
/* Campaign list row: card-like on mobile, full row on tablet+. */
.campaign-row { display: grid; grid-template-columns: 1fr; gap: var(--space-2); align-items: center; padding: var(--space-4) 0; border-bottom: 1px solid var(--color-border); }
.campaign-row:last-child { border-bottom: none; }
@media (min-width: 600px) {
.campaign-row { grid-template-columns: 1fr auto auto auto; gap: var(--space-4); }
}
/* Mobile editor pane toggle (Edit/Preview switch) β shown only on small screens */
.pane-toggle { display: inline-flex; }
/* ============================================================================
BREAKPOINT: large phones & up (>= 480px)
========================================================================== */
@media (min-width: 480px) {
.main { padding: var(--space-6); }
.export-row { grid-template-columns: 1fr auto auto auto; gap: var(--space-4); align-items: center; }
}
/* ============================================================================
BREAKPOINT: tablets & up (>= 768px) β sidebar becomes persistent
========================================================================== */
@media (min-width: 768px) {
.sidebar { position: sticky; transform: none; box-shadow: none; width: 240px; }
.menu-toggle { display: none; }
.scrim { display: none !important; }
.main { padding: var(--space-8); }
.empty-state { padding: var(--space-12) var(--space-6); }
/* Editor: dual-pane (editor + preview side by side) */
.editor-wrap { grid-template-columns: 1fr 1fr; gap: var(--space-6); }
/* On tablet+ we have both panes visible, so the mobile toggle is hidden */
.pane-toggle { display: none; }
.editor-pane.is-mobile-hidden { display: flex; }
}
/* ============================================================================
BREAKPOINT: laptops & up (>= 1024px)
========================================================================== */
@media (min-width: 1024px) {
.main { max-width: 1200px; }
}
/* ============================================================================
BREAKPOINT: wide desktops (>= 1440px)
========================================================================== */
@media (min-width: 1440px) {
.main { max-width: 1320px; padding: var(--space-12); }
}
/* ============================================================================
SMALL PHONES (< 360px) β last-ditch safety: prevent overflow
========================================================================== */
@media (max-width: 359px) {
.auth-card { padding: var(--space-3); }
.btn { padding: 0 var(--space-3); }
.page-title { font-size: 1.25rem; }
}
/* ============================================================================
MOBILE editor pane switching: on < md, show only the active pane (edit OR
preview) to avoid endless scrolling; a toggle switches between them.
========================================================================== */
@media (max-width: 767px) {
.editor-pane.is-mobile-hidden { display: none; }
}
/* Reduced motion preference (a11y) */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
/* Print: clean export-friendly */
@media print {
.sidebar, .menu-toggle, .toast-container, .pane-toggle, .btn { display: none !important; }
.main { padding: 0; max-width: none; }
}
|