/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[14].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/layout.tsx","import":"Geist","arguments":[{"subsets":["latin"],"display":"swap","variable":"--font-sans"}],"variableName":"sans"} ***!
  \*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/* cyrillic-ext */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/f639721981034f88-s.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/9766a7e9e2e0ad5a-s.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/b66cf8e69499582a-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/aa016aab0e6d1295-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/22a5144ee8d83bca-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}@font-face {font-family: 'Geist Fallback';src: local("Arial");ascent-override: 95.94%;descent-override: 28.16%;line-gap-override: 0.00%;size-adjust: 104.76%
}.__className_246ccd {font-family: 'Geist', 'Geist Fallback';font-style: normal
}.__variable_246ccd {--font-sans: 'Geist', 'Geist Fallback'
}

/*!**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[14].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/layout.tsx","import":"Geist_Mono","arguments":[{"subsets":["latin"],"display":"swap","variable":"--font-mono"}],"variableName":"mono"} ***!
  \**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/* cyrillic-ext */
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/013b72fa676f92e0-s.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/b9408752a0c24fb9-s.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* symbols2 */
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/65f03d54ccadf4a8-s.woff2) format('woff2');
  unicode-range: U+2000-2001, U+2004-2008, U+200A, U+23B8-23BD, U+2500-259F;
}
/* vietnamese */
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/e038a29029a234f2-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/2b5b02fc7e511755-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/7d4881bb7e1bf84d-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}@font-face {font-family: 'Geist Mono Fallback';src: local("Arial");ascent-override: 74.67%;descent-override: 21.92%;line-gap-override: 0.00%;size-adjust: 134.59%
}.__className_c29908 {font-family: 'Geist Mono', 'Geist Mono Fallback';font-style: normal
}.__variable_c29908 {--font-mono: 'Geist Mono', 'Geist Mono Fallback'
}

/*!*************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[3]!./app/globals.css ***!
  \*************************************************************************************************************************************************************************************************************************************************************/
:root {
  color-scheme: light;
  --bg: #fbfaf8;          /* paper, not grey */
  --panel: #ffffff;
  --panel-2: #f2f1ed;
  --border: rgba(20, 20, 16, 0.09);
  --text: #100f0d;
  --muted: #6e6d67;
  --accent: #007a5c;      /* the brand green, one shade deeper so it reads as ink */
  --accent-hover: #00654c;
  --accent-soft: rgba(0, 122, 92, 0.07);
  --accent-ink: #ffffff;
  --ink: #111111;
  --danger: #c0290c;
  --warn-text: #7a4b00;
  --warn-bg: #fff6e5;
  --warn-border: #f0c67a;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(20, 20, 15, 0.04), 0 8px 24px rgba(20, 20, 15, 0.05);

  /* --- the premium layer's own tokens ------------------------------------
     Surfaces are built from a tray, a hairline and an inner core rather than
     from a 1px grey box. See the DOUBLE BEZEL block further down. */
  --shell: rgba(16, 15, 13, 0.035);     /* the tray a card sits in */
  --hair: rgba(16, 15, 13, 0.10);       /* the hairline around the core */
  --hair-soft: rgba(16, 15, 13, 0.05);  /* the outer hairline of the tray */
  --sheen: rgba(255, 255, 255, 0.9);    /* the light catching the top edge */
  --ambient: 0 22px 48px -34px rgba(16, 15, 13, 0.16);
  --lift: 0 18px 40px -30px rgba(16, 15, 13, 0.14);
  --lift-sm: 0 8px 18px -12px rgba(16, 15, 13, 0.12);
  --lift-hover: 0 30px 60px -38px rgba(16, 15, 13, 0.20);
  --recess: inset 0 2px 5px -4px rgba(16, 15, 13, 0.22);
  --grain: 0.035;
}

/* Dark theme.
   The green stays: it is the brand mark and it still clears contrast on a dark
   panel. Everything around it is rebuilt rather than inverted, because a
   straight inversion turns the warm off-white into a cold blue-grey and the
   soft shadows into glowing halos. --ink stays dark on purpose: the few chips
   built on it carry white text, so flipping it would make them unreadable. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #08090b;          /* near-OLED, so the hairlines and the glass have somewhere to sit */
  --panel: #101216;
  --panel-2: #181b21;
  --border: rgba(255, 255, 255, 0.09);
  --text: #f2f3f2;
  --muted: #8b8f96;
  --accent: #2fbe89;
  --accent-hover: #3ed49b;
  --accent-soft: rgba(47, 190, 137, 0.13);
  --accent-ink: #04140e;
  --ink: #0d0e10;
  --danger: #ff6b52;
  --warn-text: #ffd79a;
  --warn-bg: #33280f;
  --warn-border: #6b5220;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.45);

  --shell: rgba(255, 255, 255, 0.035);
  --hair: rgba(255, 255, 255, 0.08);
  --hair-soft: rgba(255, 255, 255, 0.045);
  --sheen: rgba(255, 255, 255, 0.10);
  --ambient: 0 30px 70px -30px rgba(0, 0, 0, 0.85);
  --lift: 0 20px 44px -32px rgba(0, 0, 0, 0.75);
  --lift-sm: 0 8px 20px -12px rgba(0, 0, 0, 0.5);
  --lift-hover: 0 40px 80px -34px rgba(0, 0, 0, 0.55);
  --recess: inset 0 2px 6px -4px rgba(0, 0, 0, 0.5);
  --grain: 0.05;
}

/* Shared by both themes. Motion curves live here so nothing in the app can
   quietly fall back to a default ease, which is the single tell that separates
   software that feels made from software that feels generated. */
:root {
  --sans: var(--font-sans), ui-sans-serif, system-ui, sans-serif;
  --mono: var(--font-mono), ui-monospace, "SF Mono", Menlo, monospace;
  --r-card: 20px;
  --r-lg: 26px;
  --r-pill: 999px;
  --ease: cubic-bezier(0.32, 0.72, 0, 1);      /* weighted, settles late */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);   /* for things arriving */
  --t-fast: 220ms;
  --t: 420ms;
  --t-slow: 720ms;
}

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

html, body { height: 100%; }

body {
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; cursor: pointer; }
input, select, textarea { font: inherit; color: var(--text); }

h1, h2, h3 { letter-spacing: -0.02em; font-weight: 600; }

.shell { display: flex; flex-direction: column; height: 100dvh; }

/* ---------- top bar ---------- */
.topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 22px; border-bottom: 1px solid var(--border);
  border-top: 3px solid var(--accent); /* Shopify-admin-style green edge */
  background: var(--bg);
}
.brand {
  font-weight: 700; letter-spacing: -0.01em; font-size: 15px;
  display: flex; align-items: center; gap: 9px;
}
.gate-logo { margin-bottom: 18px; }
.brand em { color: var(--accent); font-style: normal; }
.topbar .spacer { flex: 1 1; }
.linkish {
  background: none; border: none; color: var(--muted);
  text-decoration: underline; font-size: 13px;
}
.theme-toggle {
  text-decoration: none; font-size: 15px; line-height: 1;
  padding: 5px 8px; border-radius: 8px;
}
.theme-toggle:hover { color: var(--text); background: var(--panel-2); }

/* ---------- eyebrow labels (kendo-style section index) ---------- */
.eyebrow {
  font-family: var(--mono);
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 10px;
}

/* ---------- gate ---------- */
.gate {
  max-width: 540px; margin: 10vh auto; padding: 40px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 20px; box-shadow: var(--shadow);
}
.gate h1 { font-size: 30px; margin-bottom: 8px; }
.gate h1 span { color: var(--accent); }
.gate p.sub { color: var(--muted); margin-bottom: 24px; font-size: 14.5px; }
.gate label {
  display: block; font-size: 12px; color: var(--muted);
  letter-spacing: 0.04em; text-transform: uppercase; margin: 16px 0 6px;
}
.gate input {
  width: 100%; padding: 12px 14px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel);
  font-family: var(--mono); font-size: 13px;
}
.gate input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.gate .hint { font-size: 12px; color: var(--muted); margin-top: 6px; }
.gate .err { color: var(--danger); font-size: 13px; margin-top: 12px; }

/* ---------- which model company a run goes to ---------- */
.provider-pick { display: flex; gap: 8px; margin-bottom: 2px; }
.provider-chip {
  flex: 1 1; padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--border); background: transparent;
  color: var(--muted); font-size: 13px; font-weight: 600;
  cursor: pointer; transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.provider-chip:hover { color: var(--text); }
.provider-chip.on {
  border-color: var(--accent); color: var(--accent); background: var(--accent-soft);
}
.provider-model {
  width: 100%; margin-top: 10px; padding: 11px 12px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel);
  color: var(--text); font-size: 13px;
}
.provider-caveats {
  margin: 12px 0 0; padding-left: 18px;
  font-size: 12px; line-height: 1.55; color: var(--muted);
}
.provider-caveats li { margin-bottom: 4px; }
.settings-card .provider-pick { margin-top: 6px; }
/* The note under the model buttons used to follow the model picker, which
   carried its own spacing. With the picker gone it sat 2px under the buttons
   while every label in the same card uses 14px. */
.settings-card .provider-pick + .settings-note { margin-top: 12px; }

/* ---------- buttons ---------- */
.btn {
  background: var(--accent); color: var(--accent-ink); border: 1px solid var(--accent);
  border-radius: 10px; padding: 10px 20px; font-weight: 500;
  transition: background 0.15s, border-color 0.15s;
}
.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn:disabled { opacity: 0.4; cursor: default; background: var(--accent); }
.btn.block { width: 100%; margin-top: 24px; }
.btn.ghost {
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
}
.btn.ghost:hover { background: var(--panel); border-color: var(--accent); color: var(--accent); }

/* ---------- picker screens ---------- */
.picker {
  flex: 1 1; overflow-y: auto; width: 100%;
  max-width: 900px; margin: 0 auto; padding: 7vh 24px 48px;
}
.picker h2 { font-size: 28px; margin-bottom: 6px; }
.picker p.sub { color: var(--muted); margin-bottom: 28px; font-size: 14.5px; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); grid-gap: 14px; gap: 14px; }
.card {
  text-align: left; background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 22px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.card:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.card h3 {
  font-size: 16px; margin-bottom: 6px;
  display: flex; align-items: center; flex-wrap: wrap; gap: 5px 8px;
}
.card .tagline { color: var(--accent); font-size: 13px; margin-bottom: 10px; }
.card .deliverable { color: var(--muted); font-size: 13px; line-height: 1.5; }

/* Listed but not runnable yet: reads as a roadmap slot, not a dead button. */
.card-soon {
  cursor: default; background: transparent;
  border-style: dashed; box-shadow: none;
}
.card-soon:hover { border-color: var(--border); box-shadow: none; }
.card-soon h3 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; color: var(--muted); }
.card-soon .deliverable { opacity: 0.75; }
.soon-badge {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.08em;
  text-transform: uppercase; font-weight: 400;
  color: var(--accent); background: var(--accent-soft);
  border: 1px solid var(--accent); border-radius: 999px; padding: 2px 9px;
}

/* ---------- brand folders & saved chats ---------- */
.new-brand { display: flex; gap: 10px; margin-bottom: 26px; max-width: 500px; }
.new-brand input {
  flex: 1 1; padding: 11px 14px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel);
}
.new-brand input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.brand-card { position: relative; padding: 0; }
.brand-open {
  display: block; width: 100%; text-align: left;
  background: none; border: none; padding: 22px; color: var(--text);
}
.brand-open h3 { font-size: 16px; margin-bottom: 6px; }

.mini-del {
  position: absolute; top: 10px; right: 10px;
  background: none; border: none; color: var(--muted);
  font-size: 13px; padding: 4px 6px; border-radius: 6px;
}
.mini-del:hover { color: var(--danger); background: var(--panel-2); }
/* Rename sits beside delete. It is not a destructive action, so it goes green
   on hover rather than red. */
.brand-rename { right: 36px; }
.brand-rename:hover { color: var(--accent); }

.chatlist { display: flex; flex-direction: column; gap: 8px; margin-bottom: 40px; }
.chatrow {
  position: relative; background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; transition: border-color 0.15s;
}
.chatrow:hover { border-color: var(--accent); }
.chatrow-open {
  display: flex; flex-direction: column; gap: 3px; width: 100%;
  text-align: left; background: none; border: none; color: var(--text);
  padding: 13px 70px 13px 16px;
}
.chatrow-title { font-weight: 500; font-size: 14px; }
.chatrow-meta { color: var(--muted); font-size: 12.5px; }
.chatrow .mini-del { top: 50%; transform: translateY(-50%); }

/* ---------- chat ---------- */
.chat { flex: 1 1; display: flex; flex-direction: column; overflow: hidden; }
.messages { flex: 1 1; overflow-y: auto; padding: 28px 0 12px; }
.messages-inner {
  max-width: 780px; margin: 0 auto; padding: 0 22px;
  display: flex; flex-direction: column; gap: 20px;
}

.role-tag {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.role-tag .tag-green { color: var(--accent); }

.msg-user {
  align-self: flex-end; max-width: 85%;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow);
  padding: 12px 16px; white-space: pre-wrap; font-size: 14.5px;
}
.msg-user img { max-width: 140px; border-radius: 8px; display: block; margin-top: 8px; }

/* Save button on an attached image. Sits over the corner of the thumbnail and
   only appears on hover, so a wall of extracted video frames still reads as
   pictures rather than as a grid of buttons. Always visible on touch, where
   there is no hover to reveal it. */
.msg-img { position: relative; display: inline-block; }
.img-save {
  position: absolute; right: 6px; bottom: 6px;
  width: 24px; height: 24px; padding: 0; line-height: 1;
  border-radius: 6px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text); font-size: 13px;
  opacity: 0; transition: opacity .12s;
}
.msg-img:hover .img-save, .img-save:focus-visible { opacity: 1; }
.img-save:hover { border-color: var(--accent); color: var(--accent); }
@media (hover: none) { .img-save { opacity: 1; } }

.msg-assistant {
  max-width: 100%;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 18px 22px;
}
.msg-assistant .md { overflow-wrap: anywhere; font-size: 14.5px; }
.md h1, .md h2, .md h3, .md h4 { margin: 18px 0 8px; line-height: 1.3; }
.md h1 { font-size: 20px; } .md h2 { font-size: 17px; } .md h3 { font-size: 15.5px; }
.md p, .md ul, .md ol, .md table, .md blockquote { margin: 8px 0; }
.md ul, .md ol { padding-left: 22px; }
.md code {
  font-family: var(--mono); font-size: 12.5px;
  background: var(--panel-2); padding: 1px 5px; border-radius: 4px;
}
.md pre {
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 10px; padding: 14px; overflow-x: auto; margin: 10px 0;
}
.md pre code { background: none; padding: 0; }
/* Tables always fit the message width - no horizontal scroll.
   fixed layout distributes columns; break-word wraps at word boundaries
   and only splits a word when it alone is wider than its cell. */
.md table {
  border-collapse: collapse; display: table;
  width: 100%; max-width: 100%; table-layout: fixed;
}
.md th, .md td {
  border: 1px solid var(--border); padding: 6px 10px; font-size: 13px;
  overflow-wrap: break-word; word-break: normal; vertical-align: top;
}
.md th { background: var(--panel-2); text-align: left; }
.md blockquote { border-left: 3px solid var(--accent); padding-left: 12px; color: var(--muted); }
.md hr { border: none; border-top: 1px solid var(--border); margin: 16px 0; }
.md a { color: var(--accent); }

.tool-note {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--accent); font-size: 11.5px; font-family: var(--mono);
  letter-spacing: 0.04em; text-transform: uppercase;
  background: rgba(0, 128, 96, 0.07); border-radius: 6px;
  padding: 3px 9px; margin-bottom: 10px;
}

.copy-row { margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap; }
.copy-row button {
  background: none; border: 1px solid var(--border); color: var(--muted);
  border-radius: 8px; padding: 4px 12px; font-size: 12px; cursor: pointer;
}
.copy-row button:hover { border-color: var(--accent); color: var(--accent); }
/* The user's own messages sit right-aligned, so their row does too. */
.rewind-row { justify-content: flex-end; }

/* ---------- composer ---------- */
.composer-wrap { border-top: 1px solid var(--border); background: var(--bg); }
.composer { max-width: 780px; margin: 0 auto; padding: 14px 22px 18px; }
.attach-strip { display: flex; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.attach-strip .thumb { position: relative; }
.attach-strip img { height: 52px; border-radius: 6px; display: block; }
.attach-strip .x {
  position: absolute; top: -6px; right: -6px; width: 18px; height: 18px;
  border-radius: 50%; border: none; background: var(--ink); color: #fff;
  font-size: 11px; line-height: 1;
}
.composer .row { display: flex; gap: 10px; align-items: flex-end; }
.composer textarea {
  flex: 1 1; resize: none; background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 15px; min-height: 48px; max-height: 200px;
}
.composer textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.starter-input {
  flex: 1 1; padding: 12px 15px; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--panel);
}
.starter-input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.iconbtn {
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: 10px; width: 46px; height: 46px; font-size: 17px;
}
.iconbtn:hover { border-color: var(--accent); color: var(--accent); }

/* guided (button-driven) composer */
.options-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.btn.option {
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  font-size: 13.5px; padding: 9px 16px; border-radius: 999px; font-weight: 500;
}
.btn.option:hover {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
}
.btn.ghost.option { color: var(--muted); border-style: dashed; }
.working { color: var(--muted); font-size: 13px; }

.usage { color: var(--muted); font-size: 11px; margin-top: 10px; font-family: var(--mono); }
.err-banner {
  max-width: 780px; margin: 0 auto 8px; padding: 0 22px;
  color: var(--danger); font-size: 13px;
}
.cursor-blink::after { content: "▍"; color: var(--accent); animation: blink 1s infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* Documents */
.docrow { display: flex; align-items: center; }
.docrow .chatrow-open { flex: 1 1; }
.docrow-actions { display: flex; align-items: center; gap: 6px; padding-right: 10px; }
.btn.mini { padding: 5px 12px; font-size: 12.5px; }
.docrow .mini-del.docdel { position: static; transform: none; }

.doc-chip {
  display: inline-block; font-size: 12.5px; margin-top: 8px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 4px 10px;
}
.attach-strip .attach-doc { margin-top: 0; background: var(--panel); }

.doc-picker {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 8px; margin-bottom: 10px;
  display: flex; flex-direction: column; gap: 4px; max-height: 220px; overflow-y: auto;
}
.doc-picker-item {
  text-align: left; background: none; border: none; color: var(--text);
  padding: 8px 10px; border-radius: 8px; font-size: 13.5px;
}
.doc-picker-item:hover { background: var(--panel-2); }
.doc-picker-empty { color: var(--muted); font-size: 13px; padding: 8px 10px; }

/* Modals (in-app replacements for native confirm/prompt) */
.modal-overlay {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(23, 23, 20, 0.4);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 16px; box-shadow: var(--shadow);
  padding: 24px; width: 100%; max-width: 420px;
}
.modal-msg { font-size: 14.5px; margin-bottom: 18px; }
.modal-input {
  width: 100%; padding: 11px 14px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel);
  margin-bottom: 18px;
}
.modal-input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
/* The action row had no top margin, so it sat against whatever came before it.
   In the simple modals the input's own margin hid that; in any modal with more
   than one field the buttons crowded the content above them. */
.modal-actions {
  display: flex; justify-content: flex-end; gap: 10px; margin-top: 24px;
}
/* A second block of fields inside a modal: separated by a rule so "what to
   fill in" and "what to do about it" read as different things. */
.modal-section {
  margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border);
}
.modal-section > label {
  display: block; font-size: 12px; color: var(--muted);
  letter-spacing: 0.04em; text-transform: uppercase; margin-bottom: 6px;
}
.modal-section .sub { margin: 0 0 12px; }
.modal-section .attach-strip { margin-bottom: 14px; }
.btn.danger { background: var(--danger); border-color: var(--danger); }

/* Warnings that need to be seen before work is lost, not after */
.warn-stack { display: flex; flex-direction: column; gap: 10px; margin-bottom: 22px; }
.warn-note {
  padding: 12px 15px; border-radius: 10px; font-size: 13.5px; line-height: 1.5;
  color: var(--warn-text); background: var(--warn-bg); border: 1px solid var(--warn-border);
}
.warn-note b { font-weight: 600; }
.warn-note.warn-hot {
  color: var(--danger); background: rgba(215, 44, 13, 0.06);
  border-color: rgba(215, 44, 13, 0.25);
}
/* Sits in the same stack as the warnings, but reports work being saved rather
   than work being at risk, so it reads as the good news it is. */
.warn-note.warn-ok {
  color: var(--accent); background: var(--accent-soft);
  border-color: rgba(0, 128, 96, 0.25);
}
.warn-note.warn-ok .linkish { color: inherit; opacity: .7; }

/* Confirmation after a brand is restored from a file */
.import-ok {
  margin-top: 12px; padding: 11px 14px; border-radius: 10px; font-size: 14px;
  color: var(--accent); background: var(--accent-soft);
  border: 1px solid var(--accent);
}

/* Technical detail, folded away until someone asks for it */
.tech {
  margin: 14px 0; border: 1px solid var(--border);
  border-radius: 10px; background: var(--panel-2);
}
.tech > summary {
  cursor: pointer; list-style: none; padding: 9px 14px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted); -webkit-user-select: none; -moz-user-select: none; user-select: none;
  display: flex; align-items: center; gap: 8px;
}
.tech > summary::-webkit-details-marker { display: none; }
.tech > summary::before {
  content: "▸"; font-size: 10px; transition: transform 0.15s; display: inline-block;
}
.tech[open] > summary::before { transform: rotate(90deg); }
.tech > summary:hover { color: var(--accent); }
.tech-body {
  padding: 2px 14px 12px; border-top: 1px solid var(--border);
  font-size: 14px;
}
.tech-body > :first-child { margin-top: 12px; }

/* Stop, in the Send button's place while a run is going. Reads as the opposite
   of Send without shouting like a delete. */
.stop-btn {
  background: var(--ink); border-color: var(--ink); color: #fff;
  display: inline-flex; align-items: center; gap: 8px;
}
.stop-btn:hover { background: #000; border-color: #000; }
.stop-btn::before {
  content: ""; width: 9px; height: 9px; border-radius: 2px;
  background: currentColor; flex: none;
}
.stop-btn:disabled { opacity: 0.55; cursor: default; }

/* Brand settings */
.settings-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 4px;
}
.settings-badge {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent);
  background: var(--accent-soft); border-radius: 999px;
  padding: 3px 10px; vertical-align: middle; margin-left: 8px; font-weight: 400;
}
.settings-card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 22px; margin-bottom: 32px;
}
.settings-card label {
  display: block; font-size: 12px; color: var(--muted);
  letter-spacing: 0.04em; text-transform: uppercase; margin: 14px 0 6px;
}
.settings-card label:first-child { margin-top: 0; }
.settings-card input, .settings-card textarea {
  width: 100%; padding: 11px 14px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel);
  resize: vertical;
}
.settings-card input:focus, .settings-card textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px;
}
/* "Fill this in from my site" */
.analyse-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 16px;
}
.analyse-note { margin: 10px 0 0; }

/* Grouped pipeline categories on the pick screen */
.skill-group { margin-bottom: 26px; }
.group-head {
  font-size: 13px; font-weight: 600; color: var(--muted);
  letter-spacing: 0.02em; margin: 0 0 10px;
  display: flex; align-items: center; gap: 10px;
}
/* A hairline running out from the label, so the groups read as bands without
   boxing every section in. */
.group-head::after {
  content: ""; flex: 1 1; height: 1px; background: var(--border);
}

/* Review Finder */
.rf-block { margin-top: 16px; }
.rf-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 16px; flex-wrap: wrap; margin: 18px 0 12px;
}
.rf-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.rf-dim { color: var(--muted); font-size: 13px; }
.rf-stars { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.rf-note { margin: 8px 0; }
.rf-list {
  display: flex; flex-direction: column; gap: 10px; margin-top: 14px;
  max-height: 60vh; overflow-y: auto;
}
.rf-row {
  display: grid; grid-template-columns: 108px 1fr; grid-gap: 14px; gap: 14px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel); padding: 12px 14px;
}
.rf-meta { display: flex; flex-direction: column; gap: 4px; }
.rf-rating { font-weight: 600; }
.rf-badge {
  font-size: 10.5px; color: var(--accent); border: 1px solid var(--accent);
  border-radius: 999px; padding: 1px 7px; width: -moz-fit-content; width: fit-content;
}
.rf-body { font-size: 14px; line-height: 1.5; display: flex; flex-direction: column; gap: 4px; }
@media (max-width: 620px) {
  .rf-row { grid-template-columns: 1fr; }
  .rf-meta { flex-direction: row; align-items: center; gap: 10px; }
}

/* TikTok Research */
.tt-modes { display: flex; gap: 8px; margin-bottom: 4px; }
.tt-label {
  display: block; font-size: 12px; color: var(--muted);
  letter-spacing: 0.04em; text-transform: uppercase; margin: 16px 0 6px;
}
.tt-note { margin: 6px 0 0; font-size: 12.5px; }
.tt-grid { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px; gap: 20px; }
.tt-area {
  width: 100%; padding: 11px 14px; border-radius: 10px; resize: vertical;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
}
.tt-area:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.tt-run { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 20px; }
.tt-num {
  width: 64px; margin-left: 8px; padding: 6px 8px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
}
.tt-row .rf-meta { min-width: 108px; }
.tt-stats { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12.5px; color: var(--muted); }
.tt-stats .tt-key { color: var(--accent); font-weight: 600; }
@media (max-width: 620px) { .tt-grid { grid-template-columns: 1fr; gap: 12px; } }

/* Which review apps can be read, and which cannot */
.rf-support {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--panel); padding: 14px 16px; margin-top: 16px;
}
.rf-support-grid {
  display: grid; grid-template-columns: 1fr 1fr; grid-gap: 18px; gap: 18px; margin: 12px 0;
}
.rf-support ul { margin: 6px 0 0; padding-left: 18px; font-size: 13px; }
.rf-support li { margin-bottom: 2px; }
.rf-yes, .rf-no {
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; font-weight: 600;
}
.rf-yes { color: var(--accent); }
.rf-no { color: var(--muted); }
@media (max-width: 560px) { .rf-support-grid { grid-template-columns: 1fr; gap: 12px; } }

.rf-grabber {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--panel); padding: 12px 16px; margin-top: 16px;
}
.rf-grabber summary { cursor: pointer; font-size: 13px; color: var(--muted); }
.rf-grabber .sub { margin: 10px 0; }
.rf-drag { display: flex; align-items: center; gap: 12px; margin: 12px 0; flex-wrap: wrap; }
.rf-drag a { cursor: -webkit-grab; cursor: grab; text-decoration: none; display: inline-block; }

/* Saved product photos. Named pshot, not shot: .shot is the Image Scraper's
   result tile and its rules would win over these. The hidden file input must
   not take up a row of its own, or the card grows a blank gap. */
.settings-card input[type="file"] { display: none; }
.pshot-strip { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 4px; }
.pshot { position: relative; width: 96px; }
.pshot img {
  width: 96px; height: 96px; object-fit: cover; display: block;
  border-radius: 10px; border: 1px solid var(--border); background: #fff;
}
.pshot .x {
  position: absolute; top: -7px; right: -7px; width: 20px; height: 20px;
  border-radius: 50%; border: none; background: var(--ink); color: #fff;
  font-size: 12px; line-height: 1; cursor: pointer;
}
.pshot-name {
  display: block; margin-top: 5px; font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.settings-actions {
  display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px;
}
.settings-err { color: var(--danger); font-size: 13px; margin-top: 14px; }

/* Code blocks with a copy bar */
.codeblock {
  border: 1px solid var(--border); border-radius: 10px;
  overflow: hidden; margin: 12px 0; background: var(--bg);
}
.codeblock-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 6px 8px 6px 12px;
  background: var(--panel-2); border-bottom: 1px solid var(--border);
}
.codeblock-lang {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}

/* Standalone tool, filling the screen below the top bar */
.tool-screen { max-width: 1120px; padding-top: 5vh; }

/* ---------- image scraper ---------- */
.scraper-bar { display: flex; gap: 10px; }
.scraper-url {
  flex: 1 1; background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px; font-size: 14.5px; outline: none;
}
.scraper-url:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.scraper-opts { display: flex; flex-wrap: wrap; gap: 18px; margin-top: 12px; }
.scraper-opts .opt {
  display: flex; align-items: center; gap: 7px;
  color: var(--muted); font-size: 13.5px; cursor: pointer;
}
.scraper-opts .opt input { accent-color: var(--accent); width: 15px; height: 15px; }
.scraper-err {
  margin-top: 14px; padding: 11px 14px; border-radius: 10px; font-size: 14px;
  color: var(--danger); background: rgba(215, 44, 13, 0.06);
  border: 1px solid rgba(215, 44, 13, 0.2);
}
.scraper-filters {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px;
  margin: 24px 0 14px; padding: 12px 14px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
}
.scraper-count {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted);
}
.scraper-kinds { display: flex; gap: 4px; margin-right: auto; }
.scraper-min {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted);
}
.scraper-min input { accent-color: var(--accent); width: 110px; }
.scraper-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); grid-gap: 12px; gap: 12px;
}
.shot {
  position: relative; display: block; padding: 0; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 10px; aspect-ratio: 1; transition: border-color 0.12s, box-shadow 0.12s;
}
.shot:hover { border-color: var(--accent); }
.shot.on { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.shot.on::after {
  content: "✓"; position: absolute; top: 8px; right: 8px;
  width: 21px; height: 21px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  font-size: 12px; line-height: 21px; text-align: center;
}
.shot img {
  width: 100%; height: 100%; object-fit: contain; display: block;
  background: repeating-conic-gradient(#fff 0% 25%, #f2f1ed 0% 50%) 50% / 16px 16px;
}
.shot-meta {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 5px 8px; font-family: var(--mono); font-size: 10.5px;
  color: #fff; background: linear-gradient(to top, rgba(0, 0, 0, 0.6), transparent);
  text-align: left;
}

/* Video Ad Analyser intake, replaces the message box until the video is read */
.vintake { padding: 4px 0 2px; }
.vintake-row { display: flex; gap: 10px; }
.vintake-or {
  display: flex; align-items: center; gap: 12px; margin-top: 10px;
  color: var(--muted); font-size: 13px;
}
.vintake-note { margin-top: 12px; font-size: 12.5px; }
.vintake-working { padding: 6px 0 2px; }
.vintake-stage {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 9px;
}
.vintake-bar {
  height: 6px; border-radius: 999px; background: var(--panel-2); overflow: hidden;
}
.vintake-bar span {
  display: block; height: 100%; background: var(--accent);
  border-radius: 999px; transition: width 0.25s;
}

/* One-click approval, sits just above the message box */
.approve-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.approve-btn { padding: 9px 20px; }
.approve-btn::before { content: "✓"; margin-right: 8px; font-size: 12px; }
.approve-hint { color: var(--muted); font-size: 12.5px; }

/* Product picker on a new chat */
.product-pick { margin-bottom: 10px; }
.product-pick-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 8px;
}
.product-search {
  padding: 6px 10px; border-radius: 8px; font-size: 13px;
  border: 1px solid var(--border); background: var(--panel); max-width: 200px;
}
.product-search:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.product-list { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.product-chip {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 999px; padding: 5px 14px 5px 5px; font-size: 13px;
  color: var(--text); max-width: 260px;
}
.product-chip:hover { border-color: var(--accent); }
.product-chip.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.product-chip img, .product-chip-noimg {
  width: 26px; height: 26px; border-radius: 999px; object-fit: cover;
  background: var(--panel-2); flex: 0 0 auto;
}
.product-chip-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.codeblock-copy {
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: 7px; padding: 4px 12px; font-size: 12px; font-weight: 500;
}
.codeblock-copy:hover { border-color: var(--accent); color: var(--accent); }
.codeblock pre {
  margin: 0; border: none; border-radius: 0; background: transparent;
  max-height: 460px; overflow: auto;
}
.codeblock pre code { white-space: pre; overflow-wrap: normal; word-break: normal; }
.codeblock-actions { display: flex; gap: 6px; align-items: center; }

/* Styled like the other notes in the app: hairline all the way round rather
   than a coloured bar down one edge, so callouts read as one family. */
.build-caveat {
  margin-top: 12px; padding: 10px 14px; font-size: 13.5px;
  color: var(--muted); background: var(--panel-2);
  border-radius: 10px; border: 1px solid var(--border);
}

.brand-home-btn {
  background: none; border: none; padding: 0; color: inherit;
  font: inherit; font-weight: 700; letter-spacing: -0.01em;
  border-radius: 8px;
}
.brand-home-btn:hover .wordmark { opacity: 0.65; }

/* HTML preview inside a code block */
.codeblock-tabs { display: flex; gap: 4px; }
.codeblock-tab {
  background: none; border: 1px solid transparent; color: var(--muted);
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase; padding: 3px 10px; border-radius: 999px;
}
.codeblock-tab.on {
  color: var(--accent); background: var(--accent-soft); border-color: var(--accent);
}
.codeblock-frame {
  display: block; width: 100%; height: 620px; border: none; background: #fff;
}

.mini-edit {
  position: absolute; top: 50%; right: 38px; transform: translateY(-50%);
  background: none; border: none; color: var(--muted);
  font-size: 13px; padding: 4px 6px; border-radius: 6px;
}
.mini-edit:hover { color: var(--accent); background: var(--panel-2); }

.tt-filters {
  display: flex; flex-wrap: wrap; gap: 16px 22px; margin-top: 14px;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel);
}
.tt-filters .tt-label { margin: 0; display: flex; align-items: center; gap: 8px; }

/* A tool that runs but cannot be relied on yet. Amber rather than green: this
   is a caution, not a roadmap note like "coming soon". */
.warn-badge {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.08em;
  text-transform: uppercase; font-weight: 400;
  color: var(--warn-text); background: var(--warn-bg);
  border: 1px solid var(--warn-border); border-radius: 999px; padding: 2px 9px;
  white-space: nowrap;
}

/* prototype-only marker */

/* Which version is running. Quiet when frozen, amber when it is the prototype,
   because the only dangerous confusion is thinking a working copy is the real
   thing. */
.version-badge {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px;
  white-space: nowrap;
}
.version-badge.is-proto {
  color: var(--warn-text); background: var(--warn-bg); border-color: var(--warn-border);
}

/* The moment before the app knows which version it is. Deliberately blank
   rather than a spinner: on a normal load it is gone before it registers, and a
   spinner that flashes for 100ms reads as something being wrong. */
.booting { height: 100dvh; background: var(--bg); }

/* Heavy sections inside a sent message: the transcript and the ad copy. Folded
   because they are long, already reviewed before sending, and not read twice.
   Sits inside the user bubble, so it stays quiet rather than looking like a
   control. */
.msg-user .folded {
  margin: 8px 0 0; border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel-2); padding: 6px 10px;
}
.msg-user .folded summary {
  cursor: pointer; font-size: 12.5px; color: var(--muted);
  font-family: var(--mono); letter-spacing: .02em;
}
.msg-user .folded[open] summary { margin-bottom: 6px; }
.msg-user .folded-body {
  font-size: 13px; line-height: 1.5; max-height: 320px; overflow-y: auto;
  white-space: pre-wrap;
}

/* The transcript check that runs before anything is sent. */
.vintake-head { font-weight: 600; margin-bottom: 6px; }
.vintake-edit { font-family: var(--mono); font-size: 12.5px; }
.vintake-suspect { margin: 12px 0; }
.vintake-suspect ul { margin: 8px 0 0 18px; }
.vintake-suspect li { margin-bottom: 2px; }
.vintake-confirm { margin-top: 14px; }

/* Creative QA: strategy in, verdict out. */
.sqa-select { width: auto; min-width: 220px; }
.sqa-run { margin-top: 16px; }
.sqa-report {
  margin-top: 20px; padding: 18px 20px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  white-space: pre-wrap; font-family: inherit; font-size: 14.5px; line-height: 1.6;
}

/* What a run just added to the brand's memory. Sits above the composer, quiet
   and dismissable: the memory should never change without saying so, but it is
   good news rather than a warning. */
.memory-note {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 0 auto 8px; max-width: 860px; width: 100%;
  padding: 8px 14px; border-radius: 10px; font-size: 13px;
  color: var(--accent); background: var(--accent-soft);
  border: 1px solid rgba(0, 128, 96, 0.25);
}
.memory-note .linkish { color: inherit; opacity: .7; }
.memory-box { font-family: var(--mono); font-size: 12.5px; line-height: 1.55; }

/* The stage track: how far a run has got. Reveals as it goes rather than showing
   the whole route, and calls out a stage that never opened. */
.stagetrack { max-width: 860px; margin: 4px auto 18px; width: 100%; }
.stagetrack-list { display: flex; flex-wrap: wrap; gap: 6px; }
.stagestep {
  font-size: 12px; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--muted); background: var(--panel);
}
.stagestep.is-now { border-color: var(--accent); color: var(--accent); }
.stagestep.is-todo { border-style: dashed; }
.stagestep.is-missed {
  border-color: rgba(215, 44, 13, 0.45); color: var(--danger);
}
.stagetrack-warn { margin-top: 8px; font-size: 13px; color: var(--danger); }

/* Hex codes named in plain words, under the box they came from. */
.swatches { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 4px; }
.swatch {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-family: var(--mono); color: var(--muted);
  padding: 3px 9px 3px 4px; border: 1px solid var(--border); border-radius: 999px;
}
.swatch i {
  width: 13px; height: 13px; border-radius: 50%;
  border: 1px solid var(--border); flex: none;
}
.sqa-from { margin-top: 6px; font-size: 12.5px; padding: 5px 8px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel); color: var(--muted); max-width: 260px; }
.sqa-read { margin-top: 6px; font-size: 12.5px; color: var(--accent); }
.sqa-sheet { margin: 6px 0 18px; }
.sqa-sheet .sqa-from { max-width: 320px; }

/* Reading a saved file without leaving the app. Tall and scrollable, because
   these run from a few lines to a few hundred kilobytes of reviews. */
.modal-view { max-width: 820px; width: 92vw; }
.view-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 10px;
}
.view-body {
  max-height: 60vh; overflow: auto; white-space: pre-wrap; word-break: break-word;
  font-family: var(--mono); font-size: 12.5px; line-height: 1.6;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; margin-bottom: 16px;
}
.sqa-hint { margin: 2px 0 8px; }
.sqa-sheet-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sqa-sheet-row .sqa-from { margin-top: 0; }

/* ==========================================================================
   PREMIUM LAYER
   ==========================================================================
   Everything above this line is the app's working stylesheet and still owns
   layout and behaviour. This block owns the LOOK, and it sits last on purpose
   so the look can be read, argued with, or lifted out in one piece without
   unpicking the rules that make the app function.

   The idea in one line: nothing is a flat box on a flat page. Surfaces are
   machined, light comes from above, motion has weight, and space does the
   talking. Restraint is the point, so the green appears rarely and means
   something when it does.
   ========================================================================== */

body {
  font-family: var(--sans);
  font-size: 15.5px;
  letter-spacing: -0.011em;
  text-rendering: optimizeLegibility;
}

/* The ground. Two soft fields of colour bled into the background so a dark
   page is never a dead flat black, plus a fixed film of grain so it reads as a
   surface rather than a screen. Both are fixed and click-through, which keeps
   them off the compositor's list of things to repaint while scrolling. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
}
body::after {
  opacity: var(--grain);
  z-index: 60;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}
.shell, .gate { position: relative; z-index: 1; }

/* Type. The old scale ran everything within a few points of body copy, which
   is what makes an interface read as a form. Display sizes now step up hard
   and tighten as they grow, the way type actually behaves in print. */
h1, h2, h3 { letter-spacing: -0.035em; font-weight: 600; }
.picker h2 { font-size: clamp(32px, 4.2vw, 46px); line-height: 1.04; margin-bottom: 10px; }
.gate h1 { font-size: clamp(30px, 3.6vw, 40px); line-height: 1.06; letter-spacing: -0.04em; }
.picker p.sub, .gate p.sub { font-size: 15px; max-width: 62ch; color: var(--muted); }
.picker { padding-top: 56px; padding-bottom: 96px; }
.group-head { margin-top: 56px; }

/* The eyebrow becomes a machined tag rather than a line of green text. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 11px 5px 9px;
  border-radius: var(--r-pill);
  background: var(--shell);
  box-shadow: inset 0 0 0 1px var(--hair-soft);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 18px;
}
.eyebrow::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* --- DOUBLE BEZEL --------------------------------------------------------
   A card is not one box. It is an inner core with its own hairline and its own
   catch of light along the top edge, sitting in a shallow tray with a hairline
   of its own, lifted off the page by a wide, soft ambient shadow rather than a
   hard drop shadow. Built entirely from stacked box-shadows, so no wrapper
   element is needed and the markup stays exactly as it was. */
.card,
.settings-card,
.gate,
.modal,
.memory-box,
.codeblock-frame {
  border: 0 !important;
  border-radius: var(--r-card);
  background: var(--panel);
  box-shadow:
    inset 0 1px 0 var(--sheen),
    0 0 0 1px var(--hair),
    0 0 0 6px var(--shell),
    0 0 0 7px var(--hair-soft),
    var(--ambient);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.cards { gap: 30px; }
.card { padding: 22px; }
.card h3 { font-size: 16.5px; letter-spacing: -0.02em; }

/* Hover is a lift, not a colour change. */
.card:hover {
  transform: translateY(-3px);
  box-shadow:
    inset 0 1px 0 var(--sheen),
    0 0 0 1px var(--hair),
    0 0 0 6px var(--shell),
    0 0 0 7px var(--hair-soft),
    var(--lift-hover);
}
.card:active { transform: translateY(-1px); }

/* --- Buttons -------------------------------------------------------------
   Pills, with real press physics. The scale on :active is what makes a button
   feel like it has a travel rather than a state. */
/* .sqa-run and .tt-run are rows that hold a button, not buttons. Giving them the
   pill padding pushed everything inside 20px right of the controls above them. */
.btn, .approve-btn, .stop-btn {
  border-radius: var(--r-pill);
  padding: 11px 20px;
  font-weight: 500;
  letter-spacing: -0.01em;
  border: 0;
  transition:
    transform var(--t-fast) var(--ease),
    background var(--t-fast) var(--ease),
    box-shadow var(--t-fast) var(--ease),
    color var(--t-fast) var(--ease);
}
.btn:not(.ghost) {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 1px 2px rgba(0, 0, 0, 0.18),
    0 10px 22px -14px rgba(0, 0, 0, 0.5);
}
.btn:not(.ghost):hover { transform: translateY(-1px); }
.btn:active, .approve-btn:active, .stop-btn:active { transform: scale(0.975); }
.btn.ghost {
  background: var(--shell);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--hair), inset 0 1px 0 var(--sheen);
}
.btn.ghost:hover {
  background: var(--panel-2);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--hair), inset 0 1px 0 var(--sheen), var(--lift-sm);
}
.btn:disabled { opacity: 0.32; transform: none !important; box-shadow: none; }

/* --- The top bar as a floating island ------------------------------------
   Detached from the edges, glass, and it holds a hairline instead of the old
   full-width green rule. Kept in the flow rather than fixed, because the app's
   shell is a flex column and taking it out would drop the chat's height. */
.topbar {
  margin: 12px;
  /* The inset has to clear the CORNER, not the edge. The bar's radius is 26px,
     so anything closer than that begins inside the arc and reads as crowding
     the rounded end however even the numbers look. Padding is now the radius
     plus a margin of its own, and the same rule sets the tighter phone value
     against the smaller radius there. */
  padding: 13px 34px;
  border-top: 0;
  border-bottom: 0;
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--panel) 72%, transparent);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow: inset 0 1px 0 var(--sheen), 0 0 0 1px var(--hair), var(--lift);
}

/* --- Inputs --------------------------------------------------------------
   Inset rather than outlined, so a field reads as a recess in the surface. */
.gate input, .starter-input, .new-brand input, .modal-input, .composer textarea, .settings-card input, .settings-card textarea {
  border: 0 !important;
  border-radius: 14px;
  background: var(--shell);
  box-shadow: inset 0 0 0 1px var(--hair), var(--recess);
  transition: box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.gate input:focus, .starter-input:focus, .new-brand input:focus, .modal-input:focus, .composer textarea:focus {
  outline: 0 !important;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-soft);
}

/* --- Arrival -------------------------------------------------------------
   Nothing snaps into place. Cards rise and resolve, staggered a few frames
   apart so a grid reads as one gesture rather than twenty. Runs once, on the
   screens that are read rather than worked in: the picker and the brand list.
   backwards fill keeps them invisible before their delay, and the whole thing
   is dropped for anyone who has asked the system for less motion. */
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
.picker .card { animation: rise var(--t-slow) var(--ease-out) backwards; }
.picker .card:nth-child(1) { animation-delay: 40ms; }
.picker .card:nth-child(2) { animation-delay: 80ms; }
.picker .card:nth-child(3) { animation-delay: 120ms; }
.picker .card:nth-child(4) { animation-delay: 160ms; }
.picker .card:nth-child(5) { animation-delay: 200ms; }
.picker .card:nth-child(n + 6) { animation-delay: 240ms; }
.picker h2, .picker .eyebrow, .picker p.sub { animation: rise 620ms var(--ease-out) backwards; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Small screens -------------------------------------------------------
   The bezel rings eat horizontal room, so they tighten and the grid drops to a
   single column with the padding a thumb needs. */
@media (max-width: 768px) {
  .cards { grid-template-columns: 1fr; gap: 22px; }
  .picker { padding: 32px 16px 64px; }
  .topbar { margin: 8px; padding: 11px 22px; border-radius: 20px; }
  .card, .settings-card, .gate {
    box-shadow:
      inset 0 1px 0 var(--sheen),
      0 0 0 1px var(--hair),
      0 0 0 4px var(--shell),
      var(--ambient);
  }
}

/* --- Section labels ------------------------------------------------------
   A category is a shelf, so it gets a rule that runs to the edge of the grid
   and a label small enough to stay out of the way of the cards it introduces. */
.group-head {
  display: flex;
  align-items: center;
  gap: 16px;
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 22px;
}
.group-head::after {
  content: "";
  flex: 1 1;
  height: 1px;
  background: linear-gradient(90deg, var(--hair), transparent 85%);
}

/* --- Pipeline cards ------------------------------------------------------
   Each one is a button, so it says so. A circular arrow sits in the corner and
   leans out on hover: the button-in-button idea, at card scale. Scoped to the
   pipeline grid so the brand cards, which carry their own controls, are left
   alone. */
.skill-group .card {
  position: relative;
  /* The bottom padding is the arrow's room, not decoration. It clears the
     circle plus its offset plus a gap, so a three line description can never
     run underneath it however narrow the column gets. */
  padding: 24px 24px 58px;
  min-height: 132px;
  text-align: left;
  align-items: flex-start;
}
.skill-group .card h3 { font-size: 17.5px; letter-spacing: -0.025em; margin-bottom: 8px; }
.skill-group .card .deliverable { font-size: 13.5px; line-height: 1.62; color: var(--muted); max-width: 34ch; }
.skill-group .card::after {
  content: "↗";
  position: absolute;
  right: 18px;
  bottom: 18px;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  background: var(--shell);
  box-shadow: inset 0 0 0 1px var(--hair);
  color: var(--muted);
  font-size: 12px;
  opacity: 0;
  transform: translate(-4px, 4px);
  transition: opacity var(--t) var(--ease), transform var(--t) var(--ease), color var(--t) var(--ease), background var(--t) var(--ease);
}
.skill-group .card:hover::after {
  opacity: 1;
  transform: translate(0, 0);
  color: var(--accent);
  background: var(--accent-soft);
}
.skill-group .card:focus-visible::after { opacity: 1; transform: none; }

/* A lone card in a grid should stay card-sized rather than stretching across
   the whole page, which is what auto-fit does when there is nothing to share
   the row with. */
.cards { grid-template-columns: repeat(auto-fill, minmax(272px, 1fr)); }

/* Three across is the readable width for a card carrying a title and a line of
   explanation. auto-fill was picking the column count from whatever space was
   left after the bezels, which is how the grid ended up at two on a wide
   screen and four on a wider one. Stated outright instead. */
.cards { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px; }
@media (max-width: 1080px) { .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 768px)  { .cards { grid-template-columns: 1fr; gap: 22px; } }

/* Small controls become round too. A square 32px box next to a pill button is
   the sort of mismatch that reads as unfinished even to someone who could not
   say why. */
.iconbtn, .theme-toggle, .mini-del, .mini-edit, .brand-rename, .codeblock-copy, .img-save {
  border: 0 !important;
  border-radius: var(--r-pill);
  background: var(--shell);
  box-shadow: inset 0 0 0 1px var(--hair-soft);
  transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.iconbtn:hover, .theme-toggle:hover, .codeblock-copy:hover, .img-save:hover {
  background: var(--panel-2);
  box-shadow: inset 0 0 0 1px var(--hair);
  transform: translateY(-1px);
}
.iconbtn:active, .theme-toggle:active { transform: scale(0.94); }

/* The composer is the one surface in the app that is always on screen, so it
   gets the same tray treatment as a card rather than sitting on a bare edge. */
.composer-wrap { padding: 18px 20px 22px; }
.composer {
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--panel) 70%, transparent);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  box-shadow: inset 0 1px 0 var(--sheen), 0 0 0 1px var(--hair), var(--lift);
  padding: 12px;
}
.version-badge, .settings-badge, .soon-badge, .warn-badge, .rf-badge {
  border-radius: var(--r-pill);
  border: 0 !important;
  box-shadow: inset 0 0 0 1px var(--hair);
}

/* --- Phones --------------------------------------------------------------
   Two things broke at 375px and neither was the grid: the row of brand buttons
   ran off the right edge because it had nowhere to wrap to, and the top bar's
   wordmark folded onto two lines and dragged the sign-out link with it. */
@media (max-width: 768px) {
  .new-brand { flex-wrap: wrap; gap: 10px; }
  .new-brand input { flex: 1 1 100%; min-width: 0; }
  .new-brand .btn { flex: 1 1 auto; justify-content: center; }

  .topbar { gap: 10px; }   /* padding is set with the corner radius further up */
  .topbar .brand { font-size: 13px; white-space: nowrap; }
  .topbar .version-badge { font-size: 9px; padding: 3px 8px; }
  .topbar a, .topbar .linkish { white-space: nowrap; font-size: 12px; }

  .picker h2 { font-size: clamp(28px, 9vw, 34px); }
  .gate { margin: 16px; padding: 24px 20px; }
}

/* ==========================================================================
   GLASS, NOT GLOW
   ==========================================================================
   The first pass leaned on two big fields of coloured light. Glow is cheap
   drama: it sits behind everything, tints the whole page, and says nothing
   about the surfaces themselves. Glass is the opposite. It earns its look from
   edges, from what shows through, and from where the light catches.

   So the wash drops to a whisper, and the surfaces do the work: translucent
   panels, a diagonal sheen across the top-left of every card, brighter
   hairlines, and real blur on the few things that stay put while the page
   moves under them.

   Real backdrop blur is spent only on FIXED surfaces. Twenty cards each
   blurring what is behind them, while the grid scrolls, is a repaint on every
   frame and the phone feels it first. Cards get their glass from translucency
   and light instead, which costs nothing.
   ========================================================================== */

:root {
  --glass: rgba(255, 255, 255, 0.66);
  --glass-edge: rgba(255, 255, 255, 0.9);
  --glass-sheen: rgba(255, 255, 255, 0.5);
}
:root[data-theme="dark"] {
  --glass: rgba(24, 27, 33, 0.55);
  --glass-edge: rgba(255, 255, 255, 0.14);
  --glass-sheen: rgba(255, 255, 255, 0.055);
}


/* Panes. Translucent, with the light catching the top-left corner and running
   off before it reaches the bottom, which is what tells the eye this is a sheet
   of something rather than a painted rectangle. */
.card,
.settings-card,
.gate,
.memory-box,
.codeblock-frame {
  position: relative;
  background:
    linear-gradient(148deg, var(--glass-sheen) 0%, transparent 42%),
    var(--glass);
  box-shadow:
    inset 0 1px 0 var(--glass-edge),
    inset 0 0 0 1px var(--hair-soft),
    0 0 0 1px var(--hair),
    0 0 0 6px var(--shell),
    0 0 0 7px var(--hair-soft),
    var(--ambient);
}
.card:hover {
  box-shadow:
    inset 0 1px 0 var(--glass-edge),
    inset 0 0 0 1px var(--hair),
    0 0 0 1px var(--hair),
    0 0 0 6px var(--shell),
    0 0 0 7px var(--hair-soft),
    var(--lift-hover);
}

/* The edge highlight, drawn as a hairline of light along the top of the pane
   that fades out before the corners. A uniform border is a box; a highlight
   that falls away is an edge catching a light source. */
.card::before,
.gate::before,
.settings-card::before {
  content: "";
  position: absolute;
  /* Held in by the corner radius. A full width line sits at the very top of
     the box, where the rounded corners have already curved the edge inward, so
     it carried on past the curve and hung in the air at both ends. It now
     starts and finishes where the straight part of the edge does. */
  inset: 0 var(--r-card) auto var(--r-card);
  height: 1px;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent, var(--glass-edge) 22%, var(--glass-edge) 78%, transparent);
  pointer-events: none;
}

/* Fixed surfaces get the real thing, because they are the only places where a
   blur is paid for once instead of on every scrolled frame. */
.topbar {
  background: var(--glass);
  backdrop-filter: blur(26px) saturate(190%);
  -webkit-backdrop-filter: blur(26px) saturate(190%);
  box-shadow: inset 0 1px 0 var(--glass-edge), 0 0 0 1px var(--hair), var(--lift);
  /* The blur makes the bar its own painting layer, and a layer with no depth of
     its own is painted before the chat below it. The menu lives in here, so it
     was being covered by whatever the page drew afterwards. Giving the bar a
     depth lifts the whole thing, menu included, above the page and still under
     the modals at 50. */
  position: relative;
  z-index: 20;
}
.composer {
  background: var(--glass);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
}
.modal-overlay {
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
}
.modal, .doc-picker {
  background:
    linear-gradient(148deg, var(--glass-sheen) 0%, transparent 40%),
    var(--glass);
  backdrop-filter: blur(30px) saturate(190%);
  -webkit-backdrop-filter: blur(30px) saturate(190%);
}

/* The product picker is a strip of chips, not a panel. It was swept in with the
   modals and the document picker, which gave it a pane of glass behind it and
   drew a rounded box around a row that never had one. It goes back to being a
   label and a line of chips sitting directly on the page. */
.product-pick {
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 0;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
}

/* Inputs read as recesses cut into the glass rather than tinted panels. */
.gate input, .starter-input, .new-brand input, .modal-input, .composer textarea,
.settings-card input, .settings-card textarea {
  background: rgba(0, 0, 0, 0.05);
  box-shadow: inset 0 0 0 1px var(--hair), var(--recess);
}
:root[data-theme="dark"] .gate input,
:root[data-theme="dark"] .starter-input,
:root[data-theme="dark"] .new-brand input,
:root[data-theme="dark"] .modal-input,
:root[data-theme="dark"] .composer textarea,
:root[data-theme="dark"] .settings-card input,
:root[data-theme="dark"] .settings-card textarea {
  background: rgba(0, 0, 0, 0.25);
}


/* --- The menu ------------------------------------------------------------
   A short list, so it opens in place rather than taking over the screen. */
.navmenu { position: relative; }
.navmenu-btn { display: inline-flex; align-items: center; gap: 9px; padding: 7px 14px; font-size: 13px; }
.navmenu-bars { display: inline-flex; flex-direction: column; justify-content: center; gap: 4px; width: 13px; }
.navmenu-bars i {
  height: 1.5px;
  background: currentColor;
  border-radius: 2px;
  transition: transform var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
/* Two lines turning into a cross, rather than one icon swapping for another. */
.navmenu-bars.on i:first-child { transform: translateY(2.75px) rotate(45deg); }
.navmenu-bars.on i:last-child { transform: translateY(-2.75px) rotate(-45deg); }

.navmenu-panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 40;
  min-width: 190px;
  padding: 7px;
  display: flex;
  flex-direction: column;
  border-radius: 18px;
  /* No backdrop-filter here, deliberately. The panel is opaque, so a blur
     behind it can only be invisible or harmful: an element carrying one is
     composited on its own layer, and on some graphics stacks that layer draws
     the background through rather than over what is behind it. Every measure
     said this menu was solid while it plainly was not on screen, in both
     themes, which is the signature of a compositing problem rather than a
     colour one. */
  background: var(--panel);
  box-shadow: inset 0 1px 0 var(--glass-edge), 0 0 0 1px var(--hair), var(--lift);
  animation: rise 320ms var(--ease-out) backwards;
}
.navmenu-panel button {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  text-align: left;
  padding: 10px 13px;
  border-radius: 12px;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease);
}
.navmenu-panel button:hover { background: var(--shell); }

/* --- The settings page ---------------------------------------------------
   Stacked cards, each one thing, rather than a wall of fields. */
.settings-page { max-width: 640px; }
.settings-page .settings-card { margin-top: 22px; padding: 24px; }
.settings-page .settings-card h3 { font-size: 16px; letter-spacing: -0.02em; margin-bottom: 6px; }
.settings-page .settings-note { color: var(--muted); font-size: 13.5px; line-height: 1.6; margin-bottom: 16px; }
.settings-page label {
  display: block;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 14px 0 6px;
}
.settings-page input { width: 100%; padding: 11px 13px; font-size: 14px; color: var(--text); }
.settings-page .settings-actions { display: flex; gap: 10px; margin-top: 22px; }
@media (max-width: 768px) {
  .settings-page .settings-actions { flex-wrap: wrap; }
  .settings-page .settings-actions .btn { flex: 1 1 auto; }
}

.crumb { color: var(--muted); font-size: 13px; }

/* --- The bar on a phone --------------------------------------------------
   The menu button was the last thing the bar could hold: at 390px the row ran
   off the right edge. Everything the menu or the settings page now covers is
   dropped here rather than squeezed, so what remains stays legible and
   tappable: the wordmark home, the menu, and the light switch. */
@media (max-width: 768px) {
  .topbar .crumb,
  .topbar .version-badge,
  .topbar > .linkish { display: none; }
  .navmenu-btn { padding: 7px 12px; }
}

/* ==========================================================================
   GRADIENTS
   ==========================================================================
   On surfaces and controls, not on the page. The coloured fields behind
   everything came out earlier and are staying out: they tinted the whole app
   and said nothing about the things sitting on it. A gradient earns its place
   when it describes a surface, which means light arriving from somewhere and
   falling off, so every one of these runs top to bottom or across a corner.
   None of them is a decoration laid over the page.
   ========================================================================== */

:root {
  /* The accent as a surface rather than a flat fill: lit at the top, settling
     into a deeper shade at the bottom, the way a physical key would. */
  --accent-face: linear-gradient(176deg, #12a377 0%, #007a5c 55%, #00654c 100%);
  --accent-face-hover: linear-gradient(176deg, #17b184 0%, #008766 55%, #007055 100%);
}
:root[data-theme="dark"] {
  --accent-face: linear-gradient(176deg, #4bd6a2 0%, #2fbe89 52%, #23a677 100%);
  --accent-face-hover: linear-gradient(176deg, #5ee3b0 0%, #3ed49b 52%, #2cba86 100%);
}

.btn:not(.ghost) {
  background: var(--accent-face);
  border: 0;
}
.btn:not(.ghost):hover { background: var(--accent-face-hover); }
.btn:not(.ghost):disabled { background: var(--accent-face); }

/* Ghost buttons and small controls get the same treatment at a whisper, so a
   row of mixed buttons reads as one family lit from one direction. */
.btn.ghost, .iconbtn, .theme-toggle, .navmenu-panel, .eyebrow {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0));
}
:root:not([data-theme="dark"]) .btn.ghost,
:root:not([data-theme="dark"]) .iconbtn,
:root:not([data-theme="dark"]) .theme-toggle,
:root:not([data-theme="dark"]) .navmenu-panel,
:root:not([data-theme="dark"]) .eyebrow {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(16, 15, 13, 0.02));
}

/* The panes already carry a sheen across the top-left corner. This deepens it
   and adds the second half of the story: a surface does not only catch light,
   it also loses it, so the bottom edge sinks slightly. */
.card, .settings-card, .gate, .memory-box, .codeblock-frame {
  background:
    linear-gradient(148deg, var(--glass-sheen) 0%, transparent 44%),
    linear-gradient(180deg, transparent 62%, rgba(0, 0, 0, 0.05) 100%),
    var(--glass);
}

/* Hover lights the top edge along its whole length rather than brightening the
   whole card, which is what a raked light does when a panel tilts toward you. */
.skill-group .card::before {
  background: linear-gradient(90deg, transparent, var(--glass-edge) 22%, var(--glass-edge) 78%, transparent);
  transition: background var(--t) var(--ease), opacity var(--t) var(--ease);
  opacity: 0.75;
}
.skill-group .card:hover::before {
  opacity: 1;
  background: linear-gradient(90deg, transparent, var(--accent) 18%, var(--glass-edge) 52%, var(--accent) 82%, transparent);
}

/* The wordmark stays a flat green.
   A gradient was tried here and measured worse: at the size it runs in the bar,
   the pale end of it came out at 2.9 to 1 against a light background, where
   text that size needs 4.5. It looked like a sheen at three times zoom and like
   a washed-out word at the size anyone actually reads it. Gradients belong on
   surfaces big enough to show one, not inside 13px letterforms. */

/* The sign-in screen is the one page with a single subject and room to breathe,
   so its panel gets a real ground: a deep field behind the glass instead of the
   flat page colour. This is the surface that would carry a heavier treatment
   later, and it is the only place a gradient is allowed to be the background. */
.gate {
  background:
    linear-gradient(148deg, var(--glass-sheen) 0%, transparent 44%),
    linear-gradient(163deg,
      color-mix(in srgb, var(--accent) 12%, var(--panel)) 0%,
      var(--panel) 46%,
      color-mix(in srgb, #3a2b6b 14%, var(--panel)) 100%);
}

/* Sign out was the only bare text in a row of pills. Its letters ran to the
   same 24px line the pills stop at, so while the measurements matched, its
   text sat a good 14px closer to the rounded corner than any other text in the
   bar, and read as crowding the edge. Given the same shape as its neighbours,
   the whole cluster ends on one line. */
.topbar > .linkish {
  padding: 7px 14px;
  border-radius: var(--r-pill);
  text-decoration: none;
  color: var(--muted);
  background: var(--shell);
  box-shadow: inset 0 0 0 1px var(--hair-soft);
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.topbar > .linkish:hover { color: var(--text); background: var(--panel-2); }

/* --- The ground gets the brand green ------------------------------------
   Not the field of coloured orbs that came out earlier. That was two hues
   floating over the page with no relationship to anything. This is one colour,
   the brand's own, arriving from a corner and running out across the page, so
   it reads as light falling on the ground rather than as decoration hovering
   above it.

   Fixed and click-through, so it never repaints while the page scrolls, and
   kept far enough down in opacity that body text keeps its contrast: the
   deepest point of the wash is a few percent of green over the ground colour,
   which is a tint, not a tone. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 6% -14%, var(--ground-green) 0%, transparent 58%),
    linear-gradient(168deg, var(--ground-green-2) 0%, transparent 44%, transparent 68%, var(--ground-green-3) 100%);
}

:root {
  --ground-green: rgba(0, 122, 92, 0.075);
  --ground-green-2: rgba(0, 122, 92, 0.05);
  --ground-green-3: rgba(0, 122, 92, 0.045);
}
:root[data-theme="dark"] {
  --ground-green: rgba(47, 190, 137, 0.10);
  --ground-green-2: rgba(47, 190, 137, 0.055);
  --ground-green-3: rgba(47, 190, 137, 0.05);
}

/* The role tag is a line of text above a message, not a chip. It spans the
   width of the card, so a hairline around it reads as a long empty rectangle
   rather than a badge. It gets nothing: no ring, no fill, no radius. */
.role-tag {
  border: 0;
  box-shadow: none;
  background: none;
  border-radius: 0;
  padding-left: 0;
  padding-right: 0;
}

/* --- Row controls never move under the cursor ---------------------------

   The X in a row is positioned by its own resting rule, and those rules differ
   by row: a chat row centres it with a transform, a document row lays it out
   statically. So anything here that sets a transform on hover is either
   undoing the centring or inventing one, and both show up as the button
   jumping away as you reach for it.

   The lift and the press are simply not applied to these controls, above, and
   nothing is restored here. Their feedback is colour, which changes nothing
   about where they sit. */
.mini-del:hover { background: var(--panel-2); color: var(--danger); }
.mini-edit:hover, .brand-rename:hover { background: var(--panel-2); }

/* 2. The menu becomes readable.

   It was built from the same glass as the top bar, which works for a bar that
   sits above a page and fails for a panel that sits above words. At 55% the
   headings behind it read straight through the menu items. A menu is the one
   surface that must win against whatever it covers, so it keeps the blur and
   the hairline and drops the transparency. */
.navmenu-panel {
  background: var(--panel);
  box-shadow:
    inset 0 1px 0 var(--glass-edge),
    0 0 0 1px var(--hair),
    var(--lift),
    0 2px 8px rgba(0, 0, 0, 0.18);
}

/* A row of choices a pipeline has offered. Ghost pills so they read as options
   rather than as the one obvious action, which is what the accent button means
   everywhere else in the app. */
.choice-row { flex-wrap: wrap; gap: 10px; }
.choice-btn { font-size: 13.5px; padding: 9px 16px; }

/* A brand card carries its own rename and delete controls, so the lift that
   suits a pipeline card works against it: the whole card rises three pixels as
   the pointer arrives and takes the X with it, which is the same problem in a
   different disguise. The card still answers on hover, through its shadow and
   its edge, but it holds its position. */
.brand-card:hover, .brand-card:active { transform: none; }

/* The two routes on the product page builder's opening screen. */
.route-pick {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 16px;
}

/* While a reply is on its way and has not produced a word yet. */
.waiting {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  color: var(--muted);
  font-size: 13.5px;
}
.waiting-long { flex: 1 1 100%; font-size: 12.5px; opacity: 0.85; }

/* The three dots. They were written for the embedded tools and went out with
   them; the waiting state uses them now, so they live here on their own. */
.tool-dots { display: inline-flex; align-items: center; gap: 6px; }
.tool-dots i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: dot 1.25s var(--ease) infinite;
}
/* Staggered, so the three read as one movement passing along the row rather
   than three things blinking at each other. */
.tool-dots i:nth-child(2) { animation-delay: 0.17s; }
.tool-dots i:nth-child(3) { animation-delay: 0.34s; }
@keyframes dot {
  0%, 75%, 100% { opacity: 0.2; transform: translateY(0); }
  35%           { opacity: 1;   transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .tool-dots i { opacity: 0.55; transform: none; }
}

/* The optional reference-ad panel on the Ad Copy Writer opening screen. It sits
   under the product strip, so it needs a line of its own to read as a separate
   offer rather than more of the product picker. */
.ad-ref {
  margin: 4px 0 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.ad-ref-note { margin: 6px 0 0; font-size: 12.5px; max-width: 62ch; }
.ad-ref .vintake { padding-top: 2px; }
.ad-ref-guides { margin-top: 14px; }
.ad-ref-guides .tt-area { margin-top: 8px; width: 100%; }
.ad-ref-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px; }
.ad-ref-row .vintake { padding: 0; }
.ad-ref-row .vintake-or { margin-top: 0; }
.choice-btn.on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}

/* The two upload buttons sit in different containers, and the one inside the
   video intake inherits that panel's smaller type. Same row, same size. */
.ad-ref-row .btn { font-size: 13.5px; padding: 9px 16px; }

/* Attached pictures in a message. They used to flow inline with the text, which
   put the words on the picture's baseline and left no gap between the two. */
.msg-imgs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.msg-imgs .msg-img { display: block; }
.msg-user .msg-imgs img { margin-top: 0; }
/* Just the spacing. Do not touch display: the eyebrow lays its green dot out as
   a flex item, and width and height do not apply to a plain inline box, so the
   dot collapsed to nothing and its 3px halo painted as a green square over the
   left edge of the label. */
.ad-ref-dest-head { margin-top: 14px !important; }
.ad-ref-dest { width: 100%; margin-top: 8px; }
.msg-docs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.msg-docs .doc-chip { margin-top: 0; }
/* The Kimi warning lives in the panel above the box, not in the card at the top:
   by the time it matters, the card has been scrolled off the screen. */
.ad-ref-warn { margin: 0 0 14px; }

/* The document viewer, laid out. Same box as the raw view, ordinary type instead
   of the fixed-width face, and the chat's own markdown styling inside it. */
.view-head-right { display: flex; align-items: baseline; gap: 12px; flex: 0 0 auto; }
.view-switch { font-size: 12px; white-space: nowrap; }
.view-body-read {
  white-space: normal;
  font-family: inherit;
  font-size: 14px;
}
.view-body-read > :first-child { margin-top: 0; }
.view-body-read > :last-child { margin-bottom: 0; }

/* The document viewer, laid out. Same box as the raw view, ordinary type instead
   of the fixed-width face, and the chat's own markdown styling inside it. */
.view-head-right { display: flex; align-items: baseline; gap: 12px; flex: 0 0 auto; }
.view-switch { font-size: 12px; white-space: nowrap; }
.view-body-read {
  white-space: normal;
  font-family: inherit;
  font-size: 14px;
}
.view-body-read > :first-child { margin-top: 0; }
.view-body-read > :last-child { margin-bottom: 0; }

/* Every set of work this browser is holding, including any an older version of
   the app left behind. */
.drawer-list { display: flex; flex-direction: column; gap: 10px; margin: 14px 0 16px; }
.drawer-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 16px; border-radius: 10px;
  background: var(--panel-2); border: 1px solid var(--border);
}
/* The description is the half that gives way. A flex child will not shrink below
   its longest unbroken run unless it is told it may, so without min-width:0 a
   long line of counts pushed the controls out and squeezed the name into one
   word per line. */
.drawer-what { flex: 1 1 auto; min-width: 0; }
/* The name and the in-use tag belong on one line together; the counts sit under
   them. Making the name a block put the tag on its own line and made that one
   row taller than every other. */
.drawer-what .rf-dim { margin-top: 4px; line-height: 1.45; }
/* Keep the size with its separator. Breaking between "·" and "7 KB" left the
   size stranded alone on a second line. */
.drawer-size { white-space: nowrap; }
.drawer-row.is-here { border-color: var(--accent); }
/* The row's controls sit together on the right. The confirm step swaps into the
   same slot rather than growing the row, so the list does not jump under the
   cursor when you ask to delete something. */
.drawer-actions {
  display: flex; align-items: center; gap: 10px; flex: 0 0 auto;
}
/* The question takes the description's place rather than sitting beside it. The
   name stays above it, so you can still see which set you are about to delete,
   and the row keeps its height instead of jumping under the cursor as the
   description rewraps around a question competing for the same width. */
.drawer-ask { color: var(--danger); }
/* Narrow enough that the name and the controls cannot share a line: let the
   controls drop underneath instead of crushing the name. */
@media (max-width: 620px) {
  .drawer-row { flex-wrap: wrap; }
  .drawer-actions { width: 100%; justify-content: flex-end; }
}
/* .mini-del is absolutely positioned for the brand cards, where it sits in the
   card's top corner. In this row it has to sit in the flow beside the other
   control, or it lands outside the row and cannot be seen or clicked. */
.drawer-actions .mini-del {
  position: static; font-size: 14px; line-height: 1;
}
.drawer-tag {
  margin-left: 8px; font-size: 11px; color: var(--accent);
  font-family: var(--mono); letter-spacing: 0.08em; text-transform: uppercase;
}

