/* Theme colors are CSS custom properties on :root — the TradeDealer landing
   palette (tradedealer.ru). The blocks keep their original structure:
   :root carries the DARK palette, [data-theme="light"] overrides it with the
   light one. LIGHT is the DEFAULT theme (the landing is light-first): the
   <html> element starts with data-theme="light" in index.html and app.js
   falls back to light when no persisted choice exists (see initTheme).
   The toggle in app.js switches the data-theme attribute. */
:root {
  color-scheme: dark;
  --bg: #1c1b1a;
  --panel: #2e2d2d;
  --panel-2: #222222; /* inputs, code blocks, file list */
  --line: #333333;
  --line-strong: #333333;
  --text: #f2f2f2;
  --muted: #bbb9b9;
  --accent: #fa5f1a;
  --accent-hover: #fb814b;
  --accent-soft: rgba(250, 95, 26, 0.12);
  --error: #ff6b6b;
  --warn-bg: #2a2313;
  --warn-line: #6b5a1f;
  --warn-text: #ffd98a;
  --banner-bg: #3a1418;
  --banner-line: #6b2028;
  --banner-text: #ffb3ba;
  --code-bg: #222222; /* dark surface; the hljs GitHub Dark theme paints over it */
}

:root[data-theme="light"] {
  color-scheme: light;
  --bg: #ffffff;
  --panel: #f2f2f2;
  --panel-2: #ffffff;
  --line: #e6e6e6;
  --line-strong: #e6e6e6;
  --text: #222222;
  --muted: #7c7979;
  --accent: #fa5f1a;
  --accent-hover: #fb814b;
  --accent-soft: rgba(250, 95, 26, 0.12);
  --error: #c4373f;
  --warn-bg: #fdf3d8;
  --warn-line: #dfc06a;
  --warn-text: #6d5510;
  --banner-bg: #fdecec;
  --banner-line: #f0b6bd;
  --banner-text: #9c2b36;
  --code-bg: #fafafa; /* slightly distinct from the white page/panel */
}

/* Content width (issue #1, viewport scaling): the container tracks the
   viewport width (95vw) so the editor surface scales with the browser
   resolution; a generous readability cap keeps lines sane on ultra-wide
   displays. Side padding comes from main/topbar padding. */
:root { --content-max: min(95vw, 2200px); }

/* Minimum usable height of the editor/preview surface when free space in
   the flex column runs out (tiny windows, many attached files). */
:root { --pane-floor: 9rem; }

/* Vertical gap between the create-form rows. The tab toolbar cancels it
   towards the pane so the attached tabs touch the pane's border. */
:root { --form-gap: 0.75rem; }

* { box-sizing: border-box; }

/* Viewport-scaling layout: the page is ONE flex column exactly the size of
   the viewport (dvh with a vh fallback for mobile browser chrome). The
   topbar and warnings take their natural height; main grows to fill the
   rest, and inside it the editor/preview surface is the last flex-growing
   element (see #create-form). min-height — not height — so pathological
   content (e.g. a huge attachment list) can still push the page taller
   and scroll instead of being clipped. */
body {
  margin: 0;
  min-height: 100vh; /* fallback: browsers without dvh */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
}

/* Topbar: the TradeDealer logo (#brand) on the LEFT, the theme toggle pinned
   to the RIGHT edge of the content container (space-between with only two
   children keeps them at the opposite ends at every breakpoint). */
.topbar {
  width: 100%; /* explicit width: with margin:0 auto, auto cross-axis margins
                  disable flex stretch — without this a content-sized topbar
                  would shrink and center mid-page */
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0.9rem 1.25rem 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}
/* Brand logo: the dark-theme <img> (white+orange artwork) and the light-theme
   variant (dark+orange artwork) are BOTH in the DOM; app.js toggles their
   `hidden` attributes together with the hljs stylesheets (same mechanism,
   CSP-strict — no inline styles). Height ~30px, width auto → the 280x46
   artwork scales proportionally to ~183x30, no distortion. */
#brand {
  display: inline-flex; /* the <a> hugs the visible img only */
  align-items: center;
  border-radius: 6px;
}
#brand img {
  display: block;
  height: 30px;
  width: auto; /* preserve the 280:46 aspect ratio at any height */
}
#theme-toggle {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--muted);
  padding: 0.3rem 0.8rem;
  font-size: 0.85rem;
  border-radius: 8px;
}
#theme-toggle:hover { filter: none; background: transparent; color: var(--text); border-color: var(--line-strong); }

h2 { margin: 0 0 0.75rem; font-size: 1.2rem; }

/* main grows to fill the viewport below the topbar; the create section
   inside stretches with it (sections other than #create-view keep their
   natural height). */
main {
  max-width: var(--content-max);
  margin: 0.75rem auto;
  padding: 0 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
}

section {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 1.25rem;
}

label { display: block; margin: 0.75rem 0 0.25rem; color: var(--muted); font-size: 0.9rem; }

textarea, input[type="password"], input[type="number"], input[readonly], select {
  width: 100%;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 0.6rem 0.7rem;
  font: inherit;
}

input[type="number"] { max-width: 12ch; }

/* custom dropdown arrow (CSP-safe: pure CSS triangle, no data: URI) */
.select-wrap { position: relative; display: block; }
select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  padding-right: 2rem; /* leave room so text never overlaps the arrow */
}
.select-wrap::after {
  content: "";
  position: absolute;
  right: 0.7rem;            /* breathing room from the right edge */
  top: 50%;
  transform: translateY(-50%);
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--muted);
  pointer-events: none;     /* clicks pass through to the select */
}

/* ---------- custom file control (fixes the "скомкан" native input) ---------- */
/* The native <input type="file"> is turned into an invisible full-size
   OVERLAY on top of a .file-stub box that reuses the exact metrics of the
   neighbouring controls (same padding/border/font) — so the file field has
   the same height as the selects/inputs and no longer wraps its native
   «Файл… не выб.» caption in narrow grid tracks. Clicks anywhere on the
   stub land on the overlay and open the picker; selected filenames render
   in the existing #file-list row. The input stays in the DOM with its #files
   id — the JS contract is untouched; focus-visible outlines the stub. */
.file-field { position: relative; }
.file-field input[type="file"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0; /* invisible, yet still clickable and keyboard-focusable */
  cursor: pointer;
}
.file-stub {
  display: block;
  white-space: nowrap; /* never wraps — ellipsis if the track is tiny */
  overflow: hidden;
  text-overflow: ellipsis;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 0.6rem 0.7rem; /* == the shared control padding above */
  font: inherit;
}
.file-field input:focus-visible + .file-stub {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent); /* visible focus ring on the stub */
}

/* Big editor surface (issue #1, viewport scaling): the textarea fills the
   flex-grown #editor-pane (see #create-form below) — its height tracks the
   viewport instead of a fixed vh value. Manual resizing is off because the
   pane itself now always fills the remaining window height. */
textarea { resize: none; }

/* ---------- create-form: viewport-scaling flex column ---------- */
/* The form is a flex column: #options (auto), the tab toolbar (auto), then
   the editor/preview surface — the last, flex-growing element whose bottom
   edge tracks the viewport bottom. Long content scrolls INSIDE the panes,
   so the page itself does not scroll. */
#create-view {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
#create-form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: var(--form-gap);
}

/* Options grid ABOVE the editor (PrivateBin-style compact controls): label
   + control pairs flow into as many columns as fit. Full-width rows
   (#file-list, #size-hint) span the whole grid so long file names never
   squeeze the selects. (#burn-warn is NOT a grid row: it is an absolutely
   positioned overlay — see its rule below.)
   ALIGNMENT (UI feedback): align-items:end bottom-aligns every .opt in its
   row. Each .opt ends with its control, and all controls share the same
   height — so their TOP and bottom edges land on one shared baseline
   no matter how many lines the label above takes: a multi-line label grows
   UPWARD instead of pushing its input down. */
#options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  column-gap: 1.25rem;
  row-gap: 0.25rem;
  align-items: end;
}
.opt { min-width: 0; } /* let selects/inputs shrink inside grid tracks */
.opt label { margin: 0 0 0.25rem; }
#file-list, #size-hint { grid-column: 1 / -1; } /* full-width grid rows */

/* The burn banner is a CONDITIONAL full-width strip (shown only while the
   «Удалить после просмотра» checkbox is on). To keep the controls row from
   shifting when it appears, it is taken out of the grid flow (position:
   absolute inside the relatively-positioned #options) and laid out as an
   overlay strip directly UNDER the options grid — the controls above never
   move. It spans the full width visually (inset left/right 0) and sits
   INSIDE the strip #options reserves via padding-bottom (see below):
   bottom-anchored, it can never spill into the editor toolbar. */
#options { position: relative; }
#burn-warn {
  position: absolute;
  left: 0;
  right: 0;
  /* Anchor to the BOTTOM of the reserved padding strip, not to top:100%
     (which pushed the banner past the strip into the editor toolbar
     below). bottom:0.35rem mirrors the old gap and keeps the banner
     fully inside the reserved space on every viewport. */
  bottom: 0.35rem;
}

/* «Новая запись» (issue #1): a secondary action — muted outline button that
   matches the neighbouring controls' height (same padding/border metrics as
   the selects) so the shared baseline of the options row is preserved. */
#new-pasta-btn {
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--text);
  padding: 0.6rem 1.2rem; /* == the shared control padding */
  width: 100%;
}
#new-pasta-btn:hover { filter: none; background: var(--panel-2); color: var(--text); border-color: var(--accent); }

/* Optional view limit (issue #1): checkbox + the numeric input share one
   .opt cell. The input AND its sub-label stay IN THE LAYOUT FLOW in both
   states — visibility (not display:none) keeps the cell height identical
   whether the limit is on or off, so the shared baseline of the options
   row never shifts on toggle. The sub-label is merely invisible while
   the checkbox is off (same pattern as the #burn-after input below). */
.chk { align-items: center; gap: 0.5rem; flex-wrap: wrap; }
#burn-limit { width: 1.1rem; height: 1.1rem; accent-color: var(--accent); flex: 0 0 auto; }
.chk-sub {
  margin: 0;
  font-size: 0.8rem;
  color: var(--muted);
}
.chk:not(.on) .chk-sub { visibility: hidden; }
#burn-after { max-width: 7ch; }
.chk:not(.on) #burn-after { visibility: hidden; }

/* ---------- PrivateBin-style Editor/Preview tabs above the editor ---------- */
/* Toolbar row: tabs on the left, submit action on the right. Bottom-aligned
   so the attached tabs still meet the pane's top border: margin-bottom
   cancels the form's gap, and #editor-tabs' own -1px overlaps the pane's
   top border (z-index keeps the tabs above). */
#editor-toolbar {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
  margin-bottom: calc(-1 * var(--form-gap));
}
#editor-tabs {
  display: flex;
  gap: 0.25rem;
  padding-left: 0.5rem;
  position: relative;
  z-index: 1;
  margin-bottom: -1px;
  min-width: 0;
}
.toolbar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding-bottom: 0.5rem; /* optically aligns the taller button with the tabs */
  flex-wrap: wrap;
}
#tab-edit, #tab-preview {
  background: var(--bg); /* inactive tabs look "lifted" off the page */
  color: var(--muted);
  border: 1px solid var(--line-strong);
  border-bottom: 0;
  border-radius: 8px 8px 0 0;
  padding: 0.45rem 1.1rem;
  font-size: 0.95rem;
}
#tab-edit:hover, #tab-preview:hover { filter: none; background: var(--bg); color: var(--text); }
#tab-edit[aria-selected="true"], #tab-preview[aria-selected="true"] {
  background: var(--panel-2); /* == the editor/preview pane background */
  color: var(--accent); /* active tab text highlight (brand orange) */
  border-bottom: 1px solid var(--panel-2); /* covers the pane's top border */
  box-shadow: inset 0 3px 0 var(--accent); /* active tab indicator */
}

/* Editor/preview surface: BOTH panes get identical flex sizing, so the
   visible one always occupies the whole reserved area — switching tabs
   causes no layout shift (the other pane is display:none via [hidden]). */
#editor-pane, #preview-pane {
  flex: 1 1 0;
  min-height: var(--pane-floor);
  margin-top: 0;
}
#editor-pane {
  display: flex;
  flex-direction: column;
}
#editor-pane > textarea {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
}

/* Preview tab: the SAME large surface as the editor; long content scrolls
   inside the pane instead of stretching the page. */
#preview-pane {
  overflow: auto;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 1rem;
}
/* the tab pane supplies the surrounding box — the inner renderers stay flat
   (rendering itself is identical to the recipient view via renderFormatted) */
#preview-content.secret-plain, #preview-content.secret-fixed,
#preview-content.secret-markdown, #preview-content.secret-code {
  margin: 0;
  padding: 0;
  border-radius: 0;
  background: transparent;
  max-height: none;
}
#preview-content.secret-code pre { max-height: none; }
#preview-note { margin: 0.5rem 0 0; }

/* Zero-knowledge one-liner (moved OUT of the topbar): a subtle footnote on
   its own line directly BELOW the editor/preview surface — small, muted and
   centered, so it reads as a caption of the field above, not a banner. */
.tagline {
  margin: 0.45rem 0 0;
  color: var(--muted);
  font-size: 0.8rem;
  text-align: center;
}

.row { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; margin-top: 0.75rem; }
.row label { margin: 0; }

.chk { display: flex; align-items: center; gap: 0.4rem; color: var(--text); font-size: 0.95rem; }

button {
  background: var(--accent);
  border: 0;
  color: #ffffff;
  padding: 0.6rem 1.2rem;
  border-radius: 8px;
  font: inherit;
  cursor: pointer;
}
button:hover { background: var(--accent-hover); }
button[disabled] { opacity: 0.5; cursor: default; }

/* Brand-orange focus ring for every keyboard-focusable control (links,
   buttons, inputs, selects, checkboxes). */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Links (e.g. decrypted file downloads) use the brand accent. */
a { color: var(--accent); }
a:hover { color: var(--accent-hover); }

.hint { color: var(--muted); font-size: 0.85rem; }
.error { color: var(--error); }

/* prominent secure-context warning (shown ONLY in insecure contexts) */
.banner {
  margin: 0;
  padding: 0.9rem 1rem;
  background: var(--banner-bg);
  border-bottom: 1px solid var(--banner-line);
  color: var(--banner-text);
  font-weight: 500;
}

/* inline warnings (burn-after-read etc.) — warning tone kept, palette
   aligned with the theme vars */
.warn {
  margin: 0.5rem 0 0;
  padding: 0.6rem 0.75rem;
  background: var(--warn-bg);
  border: 1px solid var(--warn-line);
  border-radius: 8px;
  color: var(--warn-text);
  font-size: 0.9rem;
}
/* the 🔥 marker inside the burn warnings picks up the brand accent */
.warn strong { color: var(--accent); }

/* The burn banner overlay (see the #burn-warn rule above) must not overlap
   the editor toolbar below #options: reserve a strip under the options grid
   exactly as tall as the banner (banner ~2.7rem + 0.35rem gap + the form's
   row gap + slack for the two-line N>1 wording). The banner itself is
   absolutely positioned inside that strip, so toggling it never moves the
   controls above. */
#options { padding-bottom: 4.6rem; }

#result-meta { margin: 0 0 0.75rem; }

/* selected-files list (full-width row of #options on the create form) */
#file-list {
  grid-column: 1 / -1;
  list-style: none;
  margin: 0.25rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  max-height: 26vh; /* a long attachment list scrolls, never pushes the page */
  overflow-y: auto;
}
#file-list li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.4rem 0.6rem;
  font-size: 0.9rem;
}
#file-list .file-name { flex: 1; overflow-wrap: anywhere; }
#file-list .file-size { color: var(--muted); white-space: nowrap; }
#file-list .file-del {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--muted);
  padding: 0.1rem 0.5rem;
  border-radius: 6px;
  font: inherit;
  line-height: 1.3;
}
#file-list .file-del:hover { background: transparent; color: var(--error); border-color: var(--error); }

/* size/limit hints: the over-limit state tints the row with the brand
   accent-soft so the problem row reads as "attention" without going full
   error-red until it actually IS an error (.error below). */
#size-hint { margin: 0.35rem 0 0; }
#size-hint.error {
  color: var(--error);
  background: var(--accent-soft);
  border-radius: 6px;
  padding: 0.25rem 0.5rem;
}

/* QR block on the share view */
.qr {
  margin-top: 1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.qr canvas {
  border: 1px solid var(--line);
  border-radius: 8px;
  image-rendering: pixelated;
  max-width: 200px;
}
.qr .hint { max-width: 320px; }

#share-url { flex: 1; }

/* «Создать ещё»: pushed ~2 lines below the QR/burn hint so the share view
   doesn't feel cramped before the call to action. */
#new-btn { margin-top: 1.75rem; }

code { background: var(--panel-2); padding: 0.1rem 0.35rem; border-radius: 4px; }

/* ---------- rendered secret + live preview (shared renderer app.js/renderFormatted) ---------- */

/* plain: normal block, line breaks preserved, proportional font */
#secret-text.secret-plain,
#preview-content.secret-plain {
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--panel-2);
  padding: 1rem;
  border-radius: 8px;
  margin: 0 0 1rem;
  max-height: 60vh;
  overflow: auto;
}

/* fixed-width: monospace, whitespace preserved */
#secret-text.secret-fixed,
#preview-content.secret-fixed {
  white-space: pre-wrap;
  word-break: break-word;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 0.95rem;
  background: var(--panel-2);
  padding: 1rem;
  border-radius: 8px;
  margin: 0 0 1rem;
  max-height: 60vh;
  overflow: auto;
}

/* source code: hljs block (theme colors come from the vendored
   github-dark / github stylesheets, one active per theme) */
#secret-text.secret-code,
#preview-content.secret-code {
  margin: 0 0 1rem;
}
#secret-text.secret-code pre,
#preview-content.secret-code pre {
  margin: 0;
  padding: 1rem;
  border-radius: 8px;
  max-height: 60vh;
  overflow: auto;
  background: var(--code-bg); /* matches the active hljs theme */
}
#secret-text.secret-code code,
#preview-content.secret-code code {
  background: transparent; /* the base `code` style is for inline snippets only */
  padding: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 0.95rem;
}

/* Line numbers for the code format (issue #1): each source line is a
   .code-line row (gutter number + code text) built by renderFormatted().
   The gutter is muted and NON-SELECTABLE (user-select:none) so selecting
   the whole block and copying yields clean code without the numbers; the
   numbers are explicit cells (not CSS counters) so they survive hljs
   highlighting and stay aligned with wrapped lines. */
.code-line {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  min-height: 1.5em;
}
.code-line .ln {
  flex: 0 0 auto;
  min-width: 2.5ch;
  text-align: right;
  color: var(--muted);
  user-select: none;
  -webkit-user-select: none;
  white-space: pre;
}
/* gutter active state: hovering a code line highlights its number with the
   brand accent and tints the row with the accent-soft wash */
.code-line:hover .ln { color: var(--accent); }
.code-line:hover { background: var(--accent-soft); }
.code-line .lc {
  flex: 1 1 auto;
  white-space: pre-wrap; /* long lines wrap INSIDE the code cell, gutter stays */
  word-break: break-word;
  min-width: 0;
}
/* per-line hljs: each .lc is its own <code class="hljs"> block (language
   auto-detection runs per line — the cross-line-highlighting tradeoff is
   accepted: multi-line constructs like block comments lose their span) */
.code-line code.hljs {
  display: inline;
  padding: 0;
  background: transparent;
  overflow-x: visible;
}

/* markdown (SANITIZED html — DOMPurify — see app.js) */
#secret-text.secret-markdown,
#preview-content.secret-markdown {
  background: var(--panel-2);
  padding: 1rem;
  border-radius: 8px;
  margin: 0 0 1rem;
  max-height: 60vh;
  overflow: auto;
  line-height: 1.6;
}
.secret-markdown > :first-child { margin-top: 0; }
.secret-markdown > :last-child { margin-bottom: 0; }
.secret-markdown h1, .secret-markdown h2, .secret-markdown h3,
.secret-markdown h4, .secret-markdown h5, .secret-markdown h6 {
  margin: 1.1em 0 0.4em;
  line-height: 1.3;
}
.secret-markdown h1 { font-size: 1.5rem; }
.secret-markdown h2 { font-size: 1.3rem; }
.secret-markdown h3 { font-size: 1.15rem; }
.secret-markdown p { margin: 0.6em 0; }
.secret-markdown ul, .secret-markdown ol { margin: 0.6em 0; padding-left: 1.6em; }
.secret-markdown li { margin: 0.2em 0; }
.secret-markdown blockquote {
  margin: 0.8em 0;
  padding: 0.2em 1em;
  border-left: 3px solid var(--line);
  color: var(--muted);
}
.secret-markdown pre {
  background: var(--code-bg);
  padding: 0.8rem 1rem;
  border-radius: 8px;
  overflow: auto;
}
.secret-markdown pre code { background: transparent; padding: 0; }
.secret-markdown table { border-collapse: collapse; margin: 0.8em 0; }
.secret-markdown th, .secret-markdown td {
  border: 1px solid var(--line);
  padding: 0.3em 0.6em;
  text-align: left;
}
.secret-markdown img { max-width: 100%; border-radius: 8px; }
.secret-markdown hr { border: 0; border-top: 1px solid var(--line); margin: 1em 0; }

#secret-files { display: flex; flex-direction: column; gap: 0.75rem; }
#secret-files img { max-width: 100%; border-radius: 8px; }
#secret-files a { color: var(--accent); }

/* ---------- responsive breakpoints (viewport scaling, issue #1) ---------- */

/* Tablets / small laptops: tighter paddings, the options grid reflows into
   fewer columns on its own (auto-fit), the editor floor keeps the textarea
   usable. */
@media (max-width: 1024px) {
  :root { --content-max: 96vw; --pane-floor: 10rem; }
  main { padding: 0 1rem; gap: 0.75rem; margin: 0.6rem auto; }
  .topbar { padding: 0.75rem 1rem 0; }
  section { padding: 1rem; }
  #options { grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); }
}

/* Phones: two option columns (selects/inputs stay comfortably wide),
   smaller chrome, the toolbar wraps instead of overlapping, no horizontal
   overflow. */
@media (max-width: 640px) {
  :root { --pane-floor: 8rem; --form-gap: 0.6rem; }
  body { font-size: 15px; }
  main { padding: 0 0.75rem; margin: 0.5rem auto; gap: 0.6rem; }
  .topbar { padding: 0.6rem 0.75rem 0; }
  section { padding: 0.85rem; }
  #options { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 0.75rem; }
  #editor-toolbar { flex-wrap: wrap; align-items: flex-end; }
  #editor-tabs { padding-left: 0.25rem; }
  #tab-edit, #tab-preview { padding: 0.4rem 0.9rem; font-size: 0.9rem; }
  .toolbar-actions { padding-bottom: 0.4rem; gap: 0.5rem; }
  #create-btn { padding: 0.5rem 1rem; font-size: 0.95rem; }
}

[hidden] { display: none !important; }
