/* Ad Studio.
   ───────────────────────────────────────────────────────────────────────────
   DIRECTION, taken as director rather than asked about.

   The first version was a form: four cards of controls, a button, and ten
   grey rectangles. Filling in a form and hoping is what cheap tools feel
   like. A professional tool answers you while you work - so the middle of
   this screen is a LIVE CANVAS that recomposes on every keystroke, and the
   controls sit beside it rather than above it.

   Rules held throughout:
     · One accent (violet), spent only on the primary action and what is
       currently selected. Everything else is greyscale.
     · Squared corners. 4px, never a lozenge.
     · Four-pixel grid. Type at 28/20/15/13/11.
     · Steps are numbered because they ARE a sequence - photo, then words,
       then look, then sizes. Numbering that encodes nothing is decoration.
     · Mobile and PC from the same file, the owner's standing order.
   ─────────────────────────────────────────────────────────────────────── */
:root{
  --bg:#08080A; --surface:#121216; --raised:#1A1A20; --sunk:#0E0E12;
  --line:#242430; --line-2:#33333F;
  --text:#FAFAFA; --text-2:#9E9EA9; --text-3:#5A5A66;
  --accent:#8B5CF6; --accent-2:#A78BFA; --accent-sunk:#1C1533;
  --good:#10B981; --bad:#F87171;
  --r:4px;
  --micro:120ms ease-out;
  --mono:'JetBrains Mono',ui-monospace,monospace;
  --display:'Space Grotesk',Inter,system-ui,sans-serif;
}
*{box-sizing:border-box}
body.ad-body{margin:0;background:var(--bg);color:var(--text);
  font:400 15px/1.55 Inter,system-ui,sans-serif;-webkit-font-smoothing:antialiased;
  min-height:100dvh}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ── Header ──────────────────────────────────────────────────────────── */
.ad-top{display:flex;align-items:center;gap:16px;background:var(--surface);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:30;
  padding:env(safe-area-inset-top,0px) 16px 0;height:calc(52px + env(safe-area-inset-top,0px))}
.ad-logo{font:600 18px/1.2 var(--display);letter-spacing:-.02em;text-decoration:none;color:var(--text)}
.ad-logo b{color:var(--accent);font-weight:600}
.ad-sep{width:1px;height:18px;background:var(--line-2)}
.ad-title{font:500 15px/1.2 var(--display);letter-spacing:-.01em}
.ad-credits{margin-left:auto;font:400 12px/1 var(--mono);color:var(--text-2);
  background:var(--raised);padding:6px 10px;border-radius:var(--r)}

/* ── Stage: rail + canvas ────────────────────────────────────────────── */
.ad-stage{display:grid;gap:16px;padding:16px;max-width:1520px;margin:0 auto;
  grid-template-columns:1fr}
@media (min-width:1060px){
  .ad-stage{grid-template-columns:376px minmax(0,1fr);padding:24px;gap:24px;
    align-items:start}
  .ad-canvasWrap{position:sticky;top:calc(76px + env(safe-area-inset-top,0px))}
}
.ad-rail{display:flex;flex-direction:column;gap:12px;min-width:0}

/* ── A step ──────────────────────────────────────────────────────────── */
.ad-step{background:var(--surface);border:1px solid var(--line);border-radius:var(--r)}
.ad-stepHead{display:flex;align-items:center;gap:10px;padding:12px 14px;
  border-bottom:1px solid var(--line)}
.ad-num{width:20px;height:20px;flex:none;border-radius:2px;background:var(--raised);
  color:var(--text-3);font:500 11px/20px var(--mono);text-align:center}
.ad-step.is-done .ad-num{background:var(--accent-sunk);color:var(--accent-2)}
.ad-stepHead h2{margin:0;font:500 13px/1.2 Inter,system-ui,sans-serif;letter-spacing:.02em}
.ad-stepHead .ad-hint{margin-left:auto;font:400 11px/1.2 var(--mono);color:var(--text-3)}
.ad-stepBody{padding:14px}

/* ── Drop zone ───────────────────────────────────────────────────────── */
.ad-drop{border:1px dashed var(--line-2);border-radius:var(--r);background:var(--sunk);
  padding:22px 14px;text-align:center;cursor:pointer;transition:border-color var(--micro),background var(--micro)}
.ad-drop:hover,.ad-drop.is-over{border-color:var(--accent);background:var(--accent-sunk)}
.ad-drop strong{display:block;font:500 15px/1.3 Inter,system-ui,sans-serif;margin-top:8px}
.ad-drop p{margin:4px 0 0;color:var(--text-3);font-size:12px}
.ad-dropIcon{width:26px;height:26px;color:var(--text-3)}
.ad-shot{display:none;gap:12px;align-items:center}
.ad-shot.is-on{display:flex}
.ad-shot img{width:64px;height:64px;object-fit:contain;border-radius:2px;background:var(--sunk);flex:none}
.ad-shotMeta{min-width:0}
.ad-shotName{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ad-shotSize{font:400 11px/1.4 var(--mono);color:var(--text-3)}
.ad-link{margin-left:auto;background:none;border:0;color:var(--accent-2);cursor:pointer;
  font:400 12px/1 Inter,system-ui,sans-serif;padding:6px}

/* ── Fields ──────────────────────────────────────────────────────────── */
.ad-f{display:flex;flex-direction:column;gap:5px;margin-bottom:12px}
.ad-f:last-child{margin-bottom:0}
.ad-f label{font:400 11px/1.2 var(--mono);color:var(--text-3);letter-spacing:.04em}
.ad-f input[type=text]{background:var(--sunk);border:1px solid var(--line-2);
  border-radius:var(--r);color:var(--text);font:400 16px/1.4 Inter,system-ui,sans-serif;
  padding:9px 12px;width:100%}
.ad-f input:focus{outline:none;border-color:var(--accent)}
.ad-row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}

/* ── Chips ───────────────────────────────────────────────────────────── */
.ad-chips{display:flex;flex-wrap:wrap;gap:6px}
.ad-chip{display:flex;align-items:center;gap:7px;padding:7px 11px 7px 7px;
  background:var(--sunk);border:1px solid var(--line-2);border-radius:var(--r);
  color:var(--text-2);font:400 12.5px/1.2 Inter,system-ui,sans-serif;cursor:pointer}
.ad-chip .ad-dot{width:14px;height:14px;border-radius:2px;flex:none}
.ad-chip[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-sunk);color:var(--text)}

/* ── Brand swatches ──────────────────────────────────────────────────── */
.ad-swatches{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.ad-sw{width:28px;height:28px;border-radius:var(--r);border:1px solid var(--line-2);
  cursor:pointer;padding:0}
.ad-sw[aria-pressed="true"]{box-shadow:0 0 0 2px var(--bg),0 0 0 3px var(--accent)}

/* ── Sizes ───────────────────────────────────────────────────────────── */
.ad-fams{display:flex;flex-direction:column;gap:2px}
.ad-fam{display:flex;align-items:center;gap:10px;padding:9px 8px;border-radius:var(--r);cursor:pointer}
.ad-fam:hover{background:var(--raised)}
.ad-fam input{accent-color:var(--accent);width:15px;height:15px;flex:none;margin:0}
.ad-famName{font-size:13px}
.ad-famSpec{font:400 10.5px/1.4 var(--mono);color:var(--text-3)}
.ad-famCost{margin-left:auto;font:400 11px/1.4 var(--mono);color:var(--text-3);flex:none}
.ad-fam.is-free .ad-famCost{color:var(--good)}

/* ── Canvas stage ────────────────────────────────────────────────────── */
.ad-canvasWrap{display:flex;flex-direction:column;gap:12px;min-width:0}
.ad-tabs{display:flex;gap:2px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);padding:3px;align-self:flex-start;max-width:100%;overflow-x:auto}
.ad-tab{background:none;border:0;color:var(--text-3);cursor:pointer;white-space:nowrap;
  font:500 12.5px/1 Inter,system-ui,sans-serif;padding:8px 14px;border-radius:2px}
.ad-tab[aria-selected="true"]{background:var(--raised);color:var(--text)}
.ad-canvasBox{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:20px;display:flex;flex-direction:column;align-items:center;gap:10px}
#adCanvas{max-width:100%;height:auto;border-radius:2px;background:var(--sunk);
  box-shadow:0 12px 40px rgba(0,0,0,.5)}
.ad-canvasNote{font:400 11px/1.5 var(--mono);color:var(--text-3);text-align:center;max-width:46ch}

/* ── Action bar ──────────────────────────────────────────────────────── */
.ad-bar{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:14px 16px;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.ad-quote{font:400 13px/1.4 var(--mono);color:var(--text-2)}
.ad-quote b{color:var(--text);font-weight:400}
.ad-say{font:400 12px/1.4 var(--mono);color:var(--text-3);min-height:17px}
.ad-say.is-bad{color:var(--bad)} .ad-say.is-good{color:var(--good)}
.ad-btn{margin-left:auto;background:var(--accent);color:#fff;border:0;border-radius:var(--r);
  font:500 14px/1 Inter,system-ui,sans-serif;padding:12px 22px;cursor:pointer;
  transition:filter var(--micro)}
.ad-btn:hover:not(:disabled){filter:brightness(1.14)}
.ad-btn:disabled{background:var(--raised);color:var(--text-3);cursor:not-allowed}
.ad-ghost{background:none;border:1px solid var(--line-2);color:var(--text-2)}
.ad-ghost:hover:not(:disabled){background:var(--raised);color:var(--text);filter:none}

/* ── The finished set ────────────────────────────────────────────────── */
.ad-setWrap{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:16px;margin:0 auto 24px;max-width:1520px}
@media (min-width:1060px){ .ad-setWrap{margin-bottom:32px} }
.ad-setHead{display:flex;align-items:baseline;gap:12px;margin-bottom:14px}
.ad-setHead h2{margin:0;font:500 13px/1.2 Inter,system-ui,sans-serif;letter-spacing:.02em}
.ad-setHead span{margin-left:auto;font:400 11px/1.4 var(--mono);color:var(--text-3)}
.ad-grid{display:flex;flex-wrap:wrap;gap:18px 14px;align-items:flex-start}
.ad-out{display:flex;flex-direction:column;gap:5px;width:var(--w);max-width:100%}
.ad-frame{width:100%;height:var(--h);position:relative;overflow:hidden;border-radius:2px;
  background:var(--sunk);border:1px solid var(--line)}
.ad-frame img,.ad-frame canvas{width:100%;height:100%;object-fit:cover;display:block}
.ad-frame.is-waiting::after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.05),transparent);
  animation:adSweep 1.5s linear infinite}
@keyframes adSweep{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
.ad-cap{display:flex;justify-content:space-between;gap:4px;flex-wrap:wrap;min-width:0;
  font:400 10.5px/1.4 var(--mono);color:var(--text-3)}
.ad-cap b{color:var(--text-2);font-weight:400;overflow-wrap:anywhere}
.ad-cap a{color:var(--accent-2);text-decoration:none}

/* ── Phone ───────────────────────────────────────────────────────────── */
@media (max-width:1059px){
  .ad-bar{position:sticky;bottom:0;z-index:20;order:9;
    margin:0 -16px;border-radius:0;border-left:0;border-right:0;border-bottom:0;
    padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px));
    box-shadow:0 -10px 30px rgba(0,0,0,.6)}
  .ad-stage{display:flex;flex-direction:column}
  .ad-btn{flex:1 1 auto;margin-left:0}
  .ad-canvasBox{padding:14px}
  /* THE PANEL GOES AFTER THE FORM ON A PHONE, and this rule used to say the
     opposite. It was right when the panel held a live preview: the thing
     that made this a tool rather than a form belonged on top. It holds an
     explanation now, and an explanation on top is a wall of text between the
     customer and the upload button - measured on a 390px screen, four cards
     of prose before "Choose a photo", with the sticky bar sitting across the
     last one. Read the screenshot, not the rule that was true last week. */
  .ad-canvasWrap{order:1}
}
@media (prefers-reduced-motion:reduce){
  .ad-frame.is-waiting::after{animation:none}
  *{transition:none!important}
}

/* ── The concepts panel ───────────────────────────────────────────────────
 *
 * This replaced the live layout preview. The old page drew exactly where the
 * text box would sit, which was honest about an engine that pasted a box of
 * type over a photograph - and that box is what the owner meant by "no
 * design, cheap look". The image model sets the type into the picture now, so
 * there is no box to preview, and drawing one would be drawing a layout that
 * will never exist. What sits here instead is the thing a customer actually
 * needs back: the three concepts and the words to paste with them. */
.ad-planHead { margin-block-end: 18px; }
.ad-planHead h2 { margin: 0 0 6px; font-size: 19px; letter-spacing: -.01em; }
.ad-planNote, .ad-planHead p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ad-dim, #8A8F98); max-width: 54ch; }

.ad-concepts { display: grid; gap: 14px; }
.ad-concept { border: 1px solid rgba(255,255,255,.10); border-radius: 14px; padding: 14px 16px; background: rgba(255,255,255,.03); }
.ad-conceptHead { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; margin-block-end: 10px; }
.ad-conceptHead b { font-size: 15.5px; }
.ad-conceptHead span { font-size: 13px; color: var(--ad-dim, #8A8F98); }

.ad-copyRow { display: grid; grid-template-columns: 104px 1fr auto; gap: 10px; align-items: start;
              padding: 7px 0; border-block-start: 1px solid rgba(255,255,255,.06); }
.ad-copyKey { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--ad-dim, #8A8F98); padding-block-start: 2px; }
.ad-copyVal { font-size: 14.5px; line-height: 1.45; overflow-wrap: anywhere; }
.ad-copyBtn { font: inherit; font-size: 12.5px; cursor: pointer; border: 1px solid rgba(255,255,255,.16);
              background: transparent; color: inherit; border-radius: 8px; padding: 4px 10px; }
.ad-copyBtn:hover { background: rgba(255,255,255,.08); }

/* The form fields the brief is written from. */
.ad-f textarea { width: 100%; font: inherit; font-size: 15px; line-height: 1.5; resize: vertical;
                 border-radius: 10px; border: 1px solid rgba(255,255,255,.14);
                 background: rgba(255,255,255,.04); color: inherit; padding: 10px 12px; }
.ad-note { margin: 6px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--ad-dim, #8A8F98); }
.ad-opt { font-weight: 400; color: var(--ad-dim, #8A8F98); }

/* The set, grouped by concept: three concepts in one flat grid is thirty
   tiles nobody can tell apart. */
.ad-groupHead { grid-column: 1 / -1; margin: 20px 0 8px; font-size: 14px; font-weight: 600;
                letter-spacing: .01em; color: var(--ad-dim, #8A8F98); }
.ad-band { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }

@media (max-width: 720px) {
  .ad-copyRow { grid-template-columns: 1fr auto; }
  .ad-copyKey { grid-column: 1 / -1; padding-block-start: 0; }
}

/* The shape tiles. The tick is drawn rather than a checkbox so the whole row
   is one button, which is what a thumb hits. */
.ad-fam{width:100%;font:inherit;color:inherit;background:transparent;border:1px solid transparent;text-align:left}
.ad-fam.is-on{background:var(--raised);border-color:rgba(255,255,255,.14)}
.ad-tick{width:15px;height:15px;flex:none;border-radius:4px;border:1.5px solid rgba(255,255,255,.28);position:relative}
.ad-tick.is-on{background:var(--accent);border-color:var(--accent)}
.ad-tick.is-on::after{content:"";position:absolute;left:4px;top:1px;width:4px;height:8px;
  border:solid #fff;border-width:0 2px 2px 0;transform:rotate(43deg)}

/* What the run will do, before there is anything to show. */
.ad-stage-card{display:flex;gap:12px;align-items:flex-start;padding:12px 14px;border-radius:12px;
  background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07)}
.ad-stageNum{flex:none;width:22px;height:22px;border-radius:999px;display:grid;place-items:center;
  font:600 11.5px/1 var(--mono,inherit);background:rgba(255,255,255,.08);color:var(--text-2,#B6BAC2)}
.ad-stage-card b{display:block;font-size:14.5px;margin-block-end:3px}
.ad-stage-card p{margin:0;font-size:13.2px;line-height:1.5;color:var(--text-3,#8A8F98);max-width:56ch}

/* ── WHAT IS HAPPENING ────────────────────────────────────────────────────
 *
 * The owner, 21 Sep 2026: "I need to see with my eyes where is stand,
 * finish? Still work?" So this is a block, not a line of status text that
 * scrolls past: a word for the state, a bar, the counts, and the stage in
 * plain language. It is filled from the server on every page open, which is
 * what makes a closed tab survivable. */
.ad-status{margin-block-end:16px;padding:14px 16px;border-radius:14px;
  border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.035)}
.ad-status.is-completed{border-color:rgba(74,222,128,.28);background:rgba(74,222,128,.06)}
.ad-status.is-failed,.ad-status.is-refunded{border-color:rgba(248,113,113,.30);background:rgba(248,113,113,.06)}

.ad-statusHead{display:flex;align-items:center;gap:9px;margin-block-end:11px;flex-wrap:wrap}
.ad-statusHead b{font-size:16px;letter-spacing:-.01em}
.ad-statusCount{margin-left:auto;font:400 12px/1.4 var(--mono,inherit);color:var(--text-3,#8A8F98)}

.ad-dot{width:8px;height:8px;border-radius:999px;flex:none;background:var(--text-3,#8A8F98)}
.ad-dot.is-live{background:#4ade80;box-shadow:0 0 0 0 rgba(74,222,128,.55);animation:adPulse 1.9s ease-out infinite}
@keyframes adPulse{70%{box-shadow:0 0 0 9px rgba(74,222,128,0)}100%{box-shadow:0 0 0 0 rgba(74,222,128,0)}}

/* The bar is the server's own number. A bar that advances on a timer lies
   exactly when a stage runs long, which is the minute somebody is watching. */
.ad-rail2{height:5px;border-radius:999px;background:rgba(255,255,255,.09);overflow:hidden}
.ad-rail2 i{display:block;height:100%;border-radius:999px;
  background:linear-gradient(90deg,#8B5CF6,#a78bfa);transition:width .45s ease}
.ad-status.is-completed .ad-rail2 i{background:linear-gradient(90deg,#22c55e,#4ade80)}
.ad-status.is-failed .ad-rail2 i,.ad-status.is-refunded .ad-rail2 i{background:#f87171}

.ad-stage2{margin:10px 0 0;font-size:14px;line-height:1.5}
.ad-aside{margin:5px 0 0;font-size:12.6px;line-height:1.5;color:var(--text-3,#8A8F98)}
.ad-statusActs{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-block-start:12px}
.ad-link2{font-size:13px;color:#a78bfa;text-decoration:none}
.ad-link2:hover{text-decoration:underline}

/* ── YOUR CAMPAIGNS ──────────────────────────────────────────────────────
 * The answer to "where go the final result". */
.ad-recentWrap{max-width:1520px;margin:0 auto;padding:8px 16px 0}
/* minmax(0,1fr), NOT the default auto track.
 *
 * This was the actual cause of the page sliding, and the flex fix below it
 * could never have worked alone. Measured: .ad-recent was 358px wide and its
 * single grid column computed to 436.656px - an `auto` track sizes itself to
 * the max-content of what is in it and is perfectly happy to overflow its own
 * container. Everything inside was then correctly filling a track that was
 * already too wide, which is why min-width:0 on the children changed nothing.
 *
 * minmax(0,1fr) caps the track at the container instead, and the ellipsis
 * further down finally has a boundary to work against. */
.ad-recent{display:grid;gap:8px;grid-template-columns:minmax(0,1fr)}
.ad-recentRow{display:flex;align-items:center;gap:12px;width:100%;min-width:0;text-align:left;
  font:inherit;color:inherit;cursor:pointer;padding:9px 11px;border-radius:12px;
  border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.025)}
.ad-recentRow:hover{background:rgba(255,255,255,.06)}
.ad-recentShots{display:flex;gap:4px;flex:none}
.ad-recentShots img{width:34px;height:34px;object-fit:cover;border-radius:6px;display:block}
/* THE ROW MUST SHRINK, NOT PUSH.
 *
 * The owner, 21 Sep 2026: "On mobile the ad studio page need be static .. my
 * finger take the whole page from side to side."
 *
 * This was the cause, measured on a 390px viewport: .ad-recentRow came out
 * 437px wide and the document scrolled to 453. min-width:0 was already here
 * and did nothing on its own, because the flex item still had `flex:0 1 auto`
 * with an auto basis - it sizes to its content first and only then considers
 * shrinking. A concept line reading "Aspirational editorial - Before and
 * after - Bold claim" is simply wider than the phone.
 *
 * flex:1 1 0 makes the basis zero, so the column takes the space that is left
 * rather than the space its text wants, and the ellipsis it already had can
 * finally do its job. Both lines get it: the date was overflowing too. */
.ad-recentMeta{display:flex;flex-direction:column;gap:2px;flex:1 1 0;min-width:0}
.ad-recentMeta b,.ad-recentMeta span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.ad-recentMeta b{font-size:13.5px}
.ad-recentMeta span{font-size:12.2px;color:var(--text-3,#8A8F98)}

@media (max-width:720px){
  .ad-statusCount{margin-left:0;width:100%}
}
