/* KFX Studio dashboard — dark product UI.
   Design notes: one accent, one font, a strict 4px spacing rhythm, and borders doing the work
   instead of shadows. Everything sits on layered greys rather than pure black so the slide
   thumbnails (which are dark photos) still read as the brightest thing on screen. */

:root {
  --bg:        #0b0b0d;
  --surface:   #131316;
  --surface-2: #191920;
  --line:      #24242c;
  --line-soft: #1c1c22;
  --text:      #f2f2f4;
  --text-dim:  #9b9ba6;
  --text-mute: #6c6c78;
  --accent:    #ff6b35;
  --accent-dk: #e2551f;
  --good:      #3ddc97;
  --bad:       #ff5f57;
  --r-sm: 8px;
  --r:    12px;
  --r-lg: 18px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* MUST outrank the component rules below. `[hidden]` only sets `display:none` at UA-stylesheet
   strength, so any later `display:` declaration silently defeats it — `.lightbox{display:grid}`
   and `.result{display:flex}` both did, leaving the lightbox permanently open over the page. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

body { display: flex; }

svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ───────── rail ───────── */
.rail {
  width: 232px;
  flex: 0 0 232px;
  background: var(--surface);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  padding: 22px 14px;
  position: sticky;
  top: 0;
  height: 100vh;
}

.brand { display: flex; align-items: center; gap: 10px; padding: 0 8px 22px; font-weight: 700; font-size: 15px; letter-spacing: -0.01em; }
/* The real mark, not a letter — see the matching note in landing.css, including why the SVG is
   inlined here rather than linked. The "K" stays in the markup and is hidden here, so all the
   brand spans update from one rule. Keep the two copies in step. */
.brand-mark {
  width: 28px; height: 28px; flex: 0 0 auto;
  border-radius: 22%;
  background: #e2551f url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024' width='1024' height='1024' role='img' aria-label='KFX Studio'%3E%3Ctitle%3EKFX Studio%3C/title%3E%3Cdefs%3E%3ClinearGradient id='bg' gradientUnits='userSpaceOnUse' x1='0' y1='0' x2='1024' y2='1024'%3E%3Cstop offset='0' stop-color='%23ff8f5e'/%3E%3Cstop offset='1' stop-color='%23e2551f'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='1024' height='1024' rx='225' fill='url(%23bg)'/%3E%3Crect x='161' y='272' width='320' height='490' rx='72' fill='%23fff' opacity='.32'/%3E%3Crect x='278' y='232' width='370' height='560' rx='88' fill='%23fff' opacity='.58'/%3E%3Crect x='393' y='192' width='470' height='640' rx='105' fill='%23fff'/%3E%3Cpath d='M568 392 L760 512 L568 632 Z' fill='url(%23bg)'/%3E%3C/svg%3E") center / contain no-repeat;
  font-size: 0; color: transparent; user-select: none;
}

.rail-nav { display: flex; flex-direction: column; gap: 2px; }
.rail-link {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px;
  border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--text-dim);
  font: inherit; font-weight: 500; text-align: left;
  cursor: pointer;
  transition: background .13s, color .13s;
}
.rail-link:hover { background: var(--surface-2); color: var(--text); }
.rail-link.is-active { background: var(--surface-2); color: var(--text); }
.rail-link.is-active svg { color: var(--accent); }

/* Workspace shortcuts in the rail. Indented under Workspaces and set a step down in weight so the
   list reads as children of that nav item rather than as more top-level destinations. */
.rail-ws { display: flex; flex-direction: column; gap: 1px; margin: 2px 0 2px 12px; }
.rail-ws-link {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px;
  border-radius: var(--r-sm);
  color: var(--text-mute);
  font-size: 13px; font-weight: 500;
  transition: background .13s, color .13s;
}
.rail-ws-link:hover { background: var(--surface-2); color: var(--text); }
.rail-ws-link.is-active { background: var(--surface-2); color: var(--text); }
/* Long business names truncate rather than wrapping — a two-line entry breaks the rhythm of the
   rail, and the full name is on the title attribute. */
.rail-ws-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.avatar.xs { width: 20px; height: 20px; border-radius: 6px; font-size: 10px; }

.rail-new { font-size: 13px; color: var(--text-mute); }
.rail-new svg { width: 16px; height: 16px; }

.rail-foot { margin-top: auto; padding: 0 8px; }
.status { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-mute); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-mute); flex: 0 0 auto; }
.dot.ok  { background: var(--good); box-shadow: 0 0 0 3px rgba(61,220,151,.13); }
.dot.bad { background: var(--bad);  box-shadow: 0 0 0 3px rgba(255,95,87,.13); }

/* Mobile chrome for the rail. Both are display:none until the drawer breakpoint below. */
.topbar { display: none; }
.rail-scrim { display: none; }

/* ───────── layout ───────── */
.main { flex: 1; min-width: 0; padding: 34px 38px 60px; overflow-y: auto; height: 100vh; }
.view { display: none; }
.view.is-active { display: block; animation: fade .18s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.head { margin-bottom: 26px; }
.head h1 { font-size: 23px; font-weight: 700; letter-spacing: -0.02em; }
.sub { color: var(--text-dim); margin-top: 5px; max-width: 62ch; }

.cols { display: grid; grid-template-columns: minmax(360px, 440px) 1fr; gap: 22px; align-items: start; }
@media (max-width: 1080px) { .cols { grid-template-columns: 1fr; } }

.panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); }

/* ───────── form ───────── */
.form { padding: 22px; display: flex; flex-direction: column; gap: 17px; }
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field-row { display: flex; gap: 12px; }
.field-row .field { flex: 1; }

label { font-size: 12.5px; font-weight: 600; color: var(--text-dim); letter-spacing: .01em; }
.opt { color: var(--text-mute); font-weight: 400; }

input, textarea, select {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 10px 12px;
  color: var(--text);
  font: inherit;
  transition: border-color .13s, box-shadow .13s;
}
textarea { resize: vertical; min-height: 96px; line-height: 1.55; }
input::placeholder, textarea::placeholder { color: var(--text-mute); }
input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(255,107,53,.13);
}
select { appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 5l3 3 3-3' stroke='%236c6c78' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; padding-right: 30px; }

.hint { font-size: 12px; color: var(--text-mute); line-height: 1.45; }
/* "optional" beside a label. A two-row textarea in a form of required fields reads as required
   unless it says otherwise, and people leave the whole form rather than guess. */
.opt {
  margin-left: 6px; font-size: 10.5px; font-weight: 600; letter-spacing: .02em;
  text-transform: uppercase; color: var(--text-mute);
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 1px 6px; border-radius: 999px; vertical-align: middle;
}
/* The generate form's steer box is a two-liner, not a paragraph field — the global 96px min-height
   would make it dominate a form whose other controls are single-line selects. */
#deckInstructions { min-height: 0; }
.err { font-size: 13px; color: var(--bad); }

/* logo drop */
.logo-drop {
  height: 92px;
  border: 1px dashed var(--line);
  border-radius: var(--r);
  background: var(--bg);
  display: grid; place-items: center;
  cursor: pointer; overflow: hidden;
  transition: border-color .13s, background .13s;
}
.logo-drop:hover { border-color: var(--accent); background: var(--surface-2); }
.logo-empty { display: flex; flex-direction: column; align-items: center; gap: 6px; color: var(--text-mute); font-size: 12.5px; }
#logoPreview { width: 62px; height: 62px; border-radius: 14px; object-fit: cover; background: #fff; }

/* chips */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--text-dim);
  border-radius: 999px;
  padding: 6px 12px;
  font: inherit; font-size: 12.5px; font-weight: 500;
  cursor: pointer;
  transition: all .13s;
}
.chip:hover { border-color: var(--text-mute); color: var(--text); }
.chip.is-on { background: var(--accent); border-color: var(--accent); color: #1a0d06; font-weight: 600; }

/* buttons */
.btn-primary {
  background: var(--accent); color: #1a0d06;
  border: 0; border-radius: var(--r);
  padding: 12px 18px;
  font: inherit; font-weight: 650; font-size: 14px;
  cursor: pointer; text-align: center; text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  transition: background .13s, transform .08s;
}
.btn-primary:hover { background: var(--accent-dk); }
.btn-primary:active { transform: translateY(1px); }
.btn-primary[disabled] { opacity: .55; cursor: not-allowed; }
.btn-primary.sm { padding: 8px 14px; font-size: 13px; border-radius: 10px; }

.btn-ghost {
  background: var(--surface-2); color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 10px;
  padding: 8px 13px; font: inherit; font-size: 13px; font-weight: 500;
  cursor: pointer; transition: all .13s;
}
.btn-ghost:hover { color: var(--text); border-color: var(--text-mute); }
.btn-ghost.xs { padding: 4px 9px; font-size: 12px; }
.btn-ghost.sm { padding: 8px 13px; font-size: 13px; }
/* Also used as an <a> (Edit workspace), which needs the underline off and the icon centred. */
a.btn-ghost { text-decoration: none; }
.btn-ghost { display: inline-flex; align-items: center; justify-content: center; gap: 7px; white-space: nowrap; }
.btn-ghost svg {
  width: 14px; height: 14px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ───────── preview ───────── */
.preview { padding: 22px; min-height: 520px; display: flex; flex-direction: column; }

.empty { margin: auto; text-align: center; max-width: 320px; }
.empty h3 { font-size: 15px; margin-bottom: 6px; }
.empty p { color: var(--text-mute); font-size: 13px; }
.phone-ghost { display: flex; gap: 9px; justify-content: center; margin-bottom: 20px; }
.phone-ghost span {
  width: 52px; height: 92px; border-radius: 9px;
  border: 1px dashed var(--line); background: var(--bg);
  display: grid; place-items: center;
  color: var(--text-mute); font-size: 12px; font-weight: 600;
}

.working { margin: auto; text-align: center; width: 100%; max-width: 300px; }
.spinner {
  width: 30px; height: 30px; margin: 0 auto 16px;
  border: 2.5px solid var(--line); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.step { color: var(--text-dim); font-size: 13.5px; margin-bottom: 14px; }
.bar { height: 3px; background: var(--line-soft); border-radius: 999px; overflow: hidden; }
.bar-fill { height: 100%; width: 0; background: var(--accent); border-radius: 999px; transition: width .5s ease; }

.result { display: flex; flex-direction: column; gap: 16px; }
.result-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.result-title { min-width: 0; }
.result-head h3 { font-size: 17px; font-weight: 650; letter-spacing: -0.015em; margin-top: 7px; }
.result-actions { display: flex; gap: 8px; flex: 0 0 auto; }
.badge {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  background: rgba(255,107,53,.13); color: var(--accent);
  font-size: 11px; font-weight: 650; text-transform: uppercase; letter-spacing: .05em;
}

.slides { display: grid; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 11px; }
.slide {
  position: relative; aspect-ratio: 9/16;
  border-radius: var(--r); overflow: hidden;
  border: 1px solid var(--line); background: var(--bg);
  cursor: zoom-in;
  transition: transform .13s, border-color .13s;
}
.slide:hover { transform: translateY(-2px); border-color: var(--text-mute); }
.slide img { width: 100%; height: 100%; object-fit: cover; display: block; }
.slide .n {
  position: absolute; top: 7px; left: 7px;
  width: 21px; height: 21px; border-radius: 6px;
  background: rgba(0,0,0,.72); backdrop-filter: blur(6px);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700;
}
.slide .mine {
  position: absolute; top: 7px; right: 7px;
  padding: 2px 7px; border-radius: 999px;
  background: var(--accent); color: #1a0d06;
  font-size: 10px; font-weight: 700;
}

.caption-box { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r); padding: 14px; }
.caption-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.caption-head span { font-size: 12px; font-weight: 600; color: var(--text-dim); }
#resCaption { font-size: 13.5px; }
.tags { margin-top: 7px; color: var(--accent); font-size: 13px; }

/* ───────── upgrade prompt (rail foot) ─────────
   Free plans only. Deliberately quiet: it lives in the rail rather than interrupting the generate
   flow, and leads with the quota bar because the number is the argument. A banner that only says
   "go premium" gets ignored; one that says "1 of 3 left" is answering a question the user already
   has. */
.upsell {
  margin: 14px 0 4px;
  padding: 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.upsell-quota { display: flex; flex-direction: column; gap: 6px; }
.upsell-quota span { font-size: 11.5px; font-weight: 600; color: var(--text-dim); }
.upsell-bar { height: 4px; border-radius: 999px; background: var(--bg); overflow: hidden; }
.upsell-bar i { display: block; height: 100%; background: var(--accent); border-radius: 999px; transition: width .3s ease; }
/* Out of runs is the one moment this should shout, so the bar turns red rather than accent. */
.upsell.is-empty .upsell-bar i { background: var(--bad); }

.upsell-line { margin-top: 9px; font-size: 11.5px; line-height: 1.45; color: var(--text-mute); }

/* One full-width CTA, nothing else. The Starter/Pro chips that used to sit here are gone: picking
   a plan inside a narrow rail, before seeing what either includes, is a decision that belongs in
   the upgrade modal — which already compares them properly. */
.upsell-plans { margin-top: 10px; }

.upsell-cta {
  display: block; width: 100%;
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
  font: inherit; font-size: 12.5px; font-weight: 700; text-align: center; cursor: pointer;
  box-shadow: 0 4px 14px rgba(255,107,53,.28);
  transition: filter .13s ease, box-shadow .13s ease, transform .13s ease;
}
.upsell-cta:hover { filter: brightness(1.08); box-shadow: 0 6px 20px rgba(255,107,53,.42); }
.upsell-cta:active { transform: translateY(1px); }

/* ───────── history ─────────
   Sits above the generate form on a workspace page. The "new" card leads the grid rather than
   trailing it: generating is the primary action here, and burying it under a year of history
   would invert that the moment somebody has more than a screen's worth. */
.history { margin-bottom: 26px; }
.history-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
.history-head h2 { font-size: 15px; font-weight: 650; letter-spacing: -0.01em; }
.history-count { color: var(--text-mute); font-size: 12.5px; }

/* The generate card — the primary action on this page, so it is filled and accent-tinted rather
   than a faint dashed outline. The old version was transparent with a grey hairline border, which
   on a near-black background made the single most important control the least visible thing on it. */
.deck-new {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  aspect-ratio: 9/16;      /* no max-height — see .deck-card */
  background: linear-gradient(160deg, rgba(255,107,53,.16), rgba(255,107,53,.05));
  border: 1.5px solid var(--accent); border-radius: var(--r-lg);
  color: var(--text); font: inherit; font-size: 13px; font-weight: 650;
  text-align: center; padding: 12px;
  box-shadow: 0 4px 18px rgba(255,107,53,.16);
  cursor: pointer; transition: filter .13s, transform .13s, box-shadow .13s;
}
.deck-new:hover { transform: translateY(-3px); filter: brightness(1.1); box-shadow: 0 10px 28px rgba(255,107,53,.3); }
/* Circled plus, so the icon reads as a button rather than a stray glyph. */
.deck-new svg {
  width: 38px; height: 38px; padding: 8px; border-radius: 50%;
  background: var(--accent); color: #fff; stroke: #fff; stroke-width: 2.5;
}

/* History cards are covers only — the slide itself is the thumbnail, the way the landing page
   showcase presents them. The hook and date used to sit under every card in a text block that made
   the grid read like a file listing; they now surface on hover, so the grid stays a wall of images
   while the detail is still one gesture away. */
.deck-card .deck-meta {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 26px 12px 11px;
  background: linear-gradient(to top, rgba(0,0,0,.88) 30%, transparent);
  opacity: 0; transform: translateY(6px);
  transition: opacity .16s ease, transform .16s ease;
  pointer-events: none;
}
.deck-card:hover .deck-meta, .deck-card:focus-visible .deck-meta { opacity: 1; transform: none; }
/* "One gesture away" assumes a gesture that exists. A touch screen has no hover, so on a phone the
   history was a wall of unlabelled thumbnails with no hook and no date anywhere — the detail was
   not one gesture away, it was unreachable. Shown outright there instead. */
@media (hover: none) {
  .deck-card .deck-meta { opacity: 1; transform: none; }
}
.deck-card .deck-meta h4 { color: #fff; }
.deck-card .deck-meta .row { color: rgba(255,255,255,.72); }

.deck-card { position: relative; }
.deck-card .deck-count {
  position: absolute; top: 8px; right: 8px;
  padding: 2px 8px; border-radius: 999px;
  background: rgba(0,0,0,.66); backdrop-filter: blur(6px);
  color: #fff; font-size: 10.5px; font-weight: 650;
}

/* archived deck modal */
/* Wide enough for a whole deck on one row. At 6 slides and 9:16 that needs ~800px of content, so
   940 leaves room for the padding without the covers shrinking to thumbnails. */
.modal-card.wide { max-width: 940px; max-height: 88vh; overflow-y: auto; }

/* One row, however many slides the deck has — `grid-auto-flow: column` beats a fixed column count
   because a 5-slide deck and a 7-slide deck both stay on a single line. */
#deckView .slides {
  grid-template-columns: none;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 9px;
}
/* Nothing in this modal opens — see the note in openArchivedDeck. Without this the cards keep the
   pointer cursor and hover lift from .slide and look clickable when they aren't. */
#deckView .slide { cursor: default; }
#deckView .slide:hover { transform: none; }

/* Below ~760px six covers on one row are unreadable, so the row scrolls sideways instead of
   squeezing. The deck still reads left-to-right, which is the point of showing it in order. */
@media (max-width: 760px) {
  #deckView .slides {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  #deckView .slides::-webkit-scrollbar { display: none; }
  #deckView .slide { flex: 0 0 108px; scroll-snap-align: start; }
}
.deck-view-meta { display: flex; align-items: center; gap: 10px; margin: 8px 0 16px; color: var(--text-mute); font-size: 12.5px; }
.deck-view-foot { display: flex; align-items: center; gap: 9px; margin-top: 18px; }
.deck-view-foot .btn-danger { margin-right: auto; margin-left: 0; }
#deckView .slides { margin-bottom: 16px; }

@media (max-width: 560px) {
  .deck-view-foot { flex-wrap: wrap; }
  .deck-view-foot .btn-danger { order: 3; margin-right: 0; }
  .deck-view-foot > * { flex: 1; text-align: center; }
}

/* ───────── library ───────── */
/* The track has to match what a card actually occupies. A 250px track held a card that could only
   ever be 140px wide — 9:16 capped at 250px tall — so every card sat in a column nearly twice its
   width and the grid read as a scatter of thumbnails with holes between them. The cap is gone (see
   .deck-card / .deck-new) and the track is now the card's real width. */
.deck-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
/* The card IS the cover: it takes the 9:16 of the slide, and the meta overlay sits inside it.
   Without a fixed ratio here the absolutely-positioned overlay would have no box to anchor to. */
.deck-card {
  /* No max-height: capping the height of a fixed-ratio card caps its WIDTH too, which is what left
     it floating in an oversized grid track. The track sizes the card now. */
  position: relative; aspect-ratio: 9/16;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); overflow: hidden;
  cursor: pointer; transition: border-color .13s, transform .13s, box-shadow .13s;
}
.deck-card:hover { border-color: var(--accent); transform: translateY(-3px); box-shadow: 0 10px 26px rgba(0,0,0,.4); }
.deck-cover { width: 100%; height: 100%; background: var(--bg); overflow: hidden; }
.deck-cover img { width: 100%; height: 100%; object-fit: cover; }
.deck-meta { padding: 13px 14px; }
.deck-meta h4 { font-size: 13.5px; font-weight: 600; line-height: 1.4; margin-bottom: 6px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.deck-meta .row { display: flex; justify-content: space-between; align-items: center; color: var(--text-mute); font-size: 11.5px; }

.empty-lib { text-align: center; padding: 70px 20px; color: var(--text-mute); }
.empty-lib h3 { color: var(--text); font-size: 15px; margin-bottom: 6px; }

/* ───────── lightbox ───────── */
.lightbox {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(0,0,0,.88); backdrop-filter: blur(10px);
  display: grid; place-items: center;
}
.lightbox img { max-width: min(420px, 84vw); max-height: 88vh; border-radius: var(--r-lg); }
.lb-close, .lb-nav {
  position: absolute; background: rgba(255,255,255,.09);
  border: 0; color: #fff; cursor: pointer;
  width: 42px; height: 42px; border-radius: 50%;
  font-size: 24px; line-height: 1;
  display: grid; place-items: center;
  transition: background .13s;
}
.lb-close:hover, .lb-nav:hover { background: rgba(255,255,255,.19); }
.lb-close { top: 22px; right: 22px; }
.lb-prev { left: 3vw; }
.lb-next { right: 3vw; }

/* ───────── account (rail foot) ─────────
   Sits under the quota readout. The sign-out control is an icon button rather than a labelled one
   so it can't be mistaken for the primary action in the rail. */
.account {
  display: flex; align-items: center; gap: 9px;
  margin-top: 14px; padding-top: 14px;
  border-top: 1px solid var(--line);
}
.account-id { min-width: 0; flex: 1; display: flex; flex-direction: column; line-height: 1.3; }
.account-name { font-size: 12.5px; font-weight: 600; }
.account-mail {
  font-size: 11px; color: var(--text-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.avatar {
  width: 28px; height: 28px; flex: 0 0 auto;
  border-radius: 50%;
  background: var(--surface-2);
  border: 1px solid var(--line);
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: var(--text-dim);
  text-transform: uppercase;
  background-size: cover; background-position: center;
}
.avatar.lg { width: 44px; height: 44px; border-radius: 12px; font-size: 17px; }

.icon-btn {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  background: transparent; color: var(--text-mute);
  border: 1px solid transparent; border-radius: var(--r-sm);
  cursor: pointer; transition: all .13s;
}
.icon-btn:hover { color: var(--text); background: var(--surface-2); border-color: var(--line); }
.icon-btn svg { width: 15px; height: 15px; }

/* ───────── headers + back link ───────── */
.head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
.ws-title { display: flex; align-items: center; gap: 13px; }

.back {
  display: inline-flex; align-items: center; gap: 4px;
  margin-bottom: 16px;
  color: var(--text-mute); text-decoration: none;
  font-size: 12.5px; font-weight: 500;
  transition: color .13s;
}
.back:hover { color: var(--text); }
.back svg { width: 14px; height: 14px; }

/* ───────── workspace grid ───────── */
.ws-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }

.ws-card {
  display: flex; flex-direction: column; gap: 11px;
  padding: 17px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  text-decoration: none; color: inherit;
  cursor: pointer;
  transition: border-color .13s, transform .08s;
}
.ws-card:hover { border-color: var(--text-mute); transform: translateY(-2px); }
.ws-card-top { display: flex; align-items: center; gap: 11px; min-width: 0; }
.ws-card h3 {
  font-size: 14.5px; font-weight: 650; letter-spacing: -0.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ws-card p {
  color: var(--text-dim); font-size: 12.5px; line-height: 1.55;
  /* Two lines then ellipsis — a long brief would otherwise make cards wildly uneven heights. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ws-card .row {
  display: flex; gap: 12px; margin-top: auto; padding-top: 3px;
  color: var(--text-mute); font-size: 11.5px;
}

/* ───────── tabs ───────── */
.tabs {
  display: flex; gap: 2px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 22px;
}
.tab {
  background: transparent; border: 0;
  border-bottom: 2px solid transparent;
  padding: 9px 14px; margin-bottom: -1px;
  font: inherit; font-size: 13px; font-weight: 550;
  color: var(--text-mute); cursor: pointer;
  transition: color .13s, border-color .13s;
}
.tab:hover { color: var(--text-dim); }
.tab.is-on { color: var(--text); border-bottom-color: var(--accent); }

.tab-panel { display: none; }
.tab-panel.is-on { display: block; animation: fade .18s ease; }

/* ───────── empty states ───────── */
.blank {
  text-align: center; padding: 66px 20px;
  color: var(--text-mute);
  border: 1px dashed var(--line);
  border-radius: var(--r-lg);
}
.blank h3 { color: var(--text); font-size: 15px; margin-bottom: 6px; }
.blank p { margin-bottom: 18px; }

/* ───────── form extras ───────── */
.form.narrow { max-width: 620px; }
.settings-form { max-width: 620px; }

/* A labelled divider — cheaper than a second panel for grouping a long settings form. */
.rule { display: flex; align-items: center; gap: 11px; color: var(--text-mute); font-size: 11.5px;
        font-weight: 600; letter-spacing: .06em; text-transform: uppercase; margin-top: 5px; }
.rule::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.form-foot { display: flex; align-items: center; gap: 10px; margin-top: 5px; }
.saved { color: var(--good); font-size: 12.5px; font-weight: 550; }
/* Destructive action sits last and to the right, away from Save. */
.btn-danger {
  margin-left: auto;
  background: transparent; color: var(--bad);
  border: 1px solid var(--line); border-radius: 10px;
  padding: 8px 13px; font: inherit; font-size: 13px; font-weight: 500;
  cursor: pointer; transition: all .13s;
}
.btn-danger:hover { border-color: var(--bad); background: rgba(255,95,87,.08); }

/* The workspace brief, shown read-only on the generate form: it's context, not an input. */
.brief {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 13px 14px;
}
.brief-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 7px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-mute);
}
.brief p {
  color: var(--text-dim); font-size: 12.5px; line-height: 1.6;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}

/* ─────────────────────── responsive ───────────────────────
   The dashboard had one media query in 478 lines. `body { display:flex }` with a
   `flex: 0 0 232px` rail that never collapses, plus 76px of horizontal padding on .main, left
   about 67px of usable width on a 375px phone. Below 860px the rail becomes a drawer and the
   document scrolls normally instead of the .main pane scrolling inside a 100vh box. */

@media (max-width: 860px) {
  body { display: block; }

  .topbar {
    display: flex; align-items: center; gap: 12px;
    position: sticky; top: 0; z-index: 40;
    padding: 10px 14px;
    background: rgba(11,11,13,.9); backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line);
  }
  .topbar-brand { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 14.5px; }
  .topbar-burger {
    width: 38px; height: 38px; padding: 10px 8px; flex: 0 0 auto;
    display: flex; flex-direction: column; justify-content: space-between;
    background: transparent; border: 1px solid var(--line); border-radius: var(--r-sm);
    cursor: pointer;
  }
  .topbar-burger span { display: block; height: 2px; background: var(--text); border-radius: 2px; transition: transform .16s, opacity .16s; }
  .topbar-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .topbar-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .topbar-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  .rail {
    position: fixed; top: 0; left: 0; z-index: 60;
    width: 270px; flex-basis: auto;
    height: 100dvh;
    transform: translateX(-100%);
    transition: transform .2s ease;
    overflow-y: auto;
  }
  .rail.is-open { transform: none; box-shadow: 0 0 60px rgba(0,0,0,.6); }
  .rail-scrim { display: block; position: fixed; inset: 0; z-index: 50; background: rgba(0,0,0,.55); }

  /* Normal document scroll: two nested scroll containers on a phone means the address bar never
     collapses and momentum scrolling fights the outer page. */
  .main { height: auto; overflow: visible; padding: 22px 16px 56px; }

  /* 16px is not a taste choice. iOS Safari zooms the page in on focusing any form control smaller
     than 16px, and never zooms back out — one tap on the business description and the rest of the
     app is oversized and scrolling sideways for the rest of the session. Everything inherits 14px
     from :root, so every field in the product had this. */
  input, textarea, select { font-size: 16px; }

  .head h1 { font-size: 20px; }
  .head-row { flex-direction: column; align-items: stretch; gap: 14px; }
  .head-row .btn-primary { align-self: flex-start; }

  /* Thumbs, not cursors. 6px of vertical padding is a ~28px target; the guideline is 44 and these
     are the controls the whole generate flow runs through. */
  .chip { padding: 9px 14px; font-size: 13px; }
  .btn-primary, .btn-ghost { padding: 12px 18px; }
  .btn-primary.sm, .btn-ghost.sm { padding: 10px 15px; }
  /* The primary action of a page goes full width — it is the one thing a thumb should not miss. */
  .form-foot .btn-primary { width: 100%; justify-content: center; }

  .cols { gap: 16px; }
  .form { padding: 17px; gap: 15px; }
  /* Stacked, these three-up rows were 90px-wide selects with clipped labels. */
  .field-row { flex-direction: column; gap: 15px; }
  .preview { padding: 16px; min-height: 0; }
  .form.narrow, .settings-form { max-width: none; }

  .ws-grid { grid-template-columns: 1fr; }
  /* .deck-grid needs no override here any more — the base rule is already this. */

  .result-head { flex-direction: column; align-items: stretch; gap: 12px; }
  .result-actions { display: flex; gap: 8px; }
  .result-actions > * { flex: 1; }

  .form-foot { flex-wrap: wrap; }
  .btn-danger { margin-left: 0; }

  .lb-prev { left: 8px; }
  .lb-next { right: 8px; }
}

@media (max-width: 520px) {
  /* 20px of scrim on each side of a modal is 40px of a 360px screen spent on nothing. The cards
     inside are already width-capped, so this only ever buys room on the smallest phones. */
  .modal { padding: 10px; }
}

@media (max-width: 420px) {
  .main { padding: 18px 13px 48px; }
  .head h1 { font-size: 18.5px; }
  .deck-grid { grid-template-columns: repeat(2, 1fr); }
  .slides { grid-template-columns: repeat(2, 1fr); }
  .chips { gap: 6px; }
}

/* ───────── confirm modal ───────── */
.modal {
  position: fixed; inset: 0; z-index: 70;
  background: rgba(0,0,0,.7); backdrop-filter: blur(4px);
  display: grid; place-items: center; padding: 20px;
}
.modal-card {
  width: 100%; max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 22px;
}
.modal-card h3 { font-size: 16px; font-weight: 650; margin-bottom: 8px; }
.modal-card p { color: var(--text-dim); font-size: 13px; line-height: 1.55; }
.modal-foot { display: flex; justify-content: flex-end; gap: 9px; margin-top: 20px; }
