/* ===========================================================================
   imagineai — the design system, as CSS.
   Source of truth: docs/design-system.md
   Nothing here invents a colour, a radius, or an easing curve. If a value is
   needed that is not below, it is a design decision — ask, do not improvise.
   =========================================================================== */

/* --- Fonts (§7) — self-hosted; the app must not depend on a CDN ----------- */

/* Display (§7) — English only. Archivo never attempts Thai; a Thai headline
   is set in Plex Sans Thai 600 instead, which is the rule, not a fallback. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/archivo-700-latin.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: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/archivo-700-latin-ext.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;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/archivo-800-latin.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: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/archivo-800-latin-ext.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;
}

/* Body, and every word of Thai. Carries both scripts at one weight and
   rhythm, so the brand does not break when the language changes. */
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/plexthai-400-latin.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: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/plexthai-400-latin-ext.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;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/plexthai-400-thai.woff2') format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/plexthai-600-latin.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: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/plexthai-600-latin-ext.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;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/plexthai-600-thai.woff2') format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}

/* Labels, meta, counts, anything in caps. */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/plexmono-400-latin.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/plexmono-400-latin-ext.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;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/plexmono-600-latin.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/plexmono-600-latin-ext.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;
}

/* --- Tokens (§6, screen) --------------------------------------------------- */

:root {
  --void:  #0b0b0c;   /* Page */
  --plate: #1c1916;   /* Card fill */
  --rule:  #37322e;   /* Hairlines, quiet panel edges */
  --dim:   #615d58;   /* 3.0 — numerals, disabled. UI only, NEVER body text. */
  --mute:  #96918c;   /* 6.3 — labels, secondary text, loud panel edges */
  --text:  #ebe7e2;   /* 16.0 — body, headings */

  /* Two accents, and they carry meaning (§6). LIFT is the Captain — waiting on
     him, his focus, his emphasis, the hub of the mark. BAMBOO is the machine —
     running, synced, done. Never swapped, never decorative: a colour that is
     doing nothing should be MUTE. */
  --lift:   #f69e7f;  /*  9.5 — you */
  --bamboo: #a2c674;  /* 10.1 — the machine */

  --ground: var(--void);
  --card:   var(--plate);
  --line:   var(--rule);
  --accent: var(--lift);

  /* §7 — three families, one job each. */
  --font-display: 'Archivo', 'IBM Plex Sans Thai', system-ui, sans-serif;
  --font-sans: 'IBM Plex Sans Thai', system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;

  /* Spacing — the page breathes; half of it is empty (§8). */
  --gap: 12px;
  --pad: 24px;
  --shell: 1320px;

  /* The one shadow in the system: hard, offset, no blur (§8). */
  --shadow: 5px 5px 0 0 var(--rule);
  --shadow-accent: 5px 5px 0 0 var(--lift);
}

/* --- Reset ------------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  overflow-x: clip;
  background: var(--ground);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
[hidden] { display: none !important; }

/* --- The mark (§4) — four blades, clockwise, 22s, the hub is still --------- */

.mark { width: 40px; height: 40px; overflow: visible; flex: none; }
.mark__rotor { transform-origin: 100px 100px; animation: mark-spin 22s linear infinite; }
.mark__blade { fill: var(--text); }
.mark__vein  { fill: none; stroke: var(--ground); stroke-width: 2.5; stroke-linecap: butt; }
.mark__hub   { fill: var(--accent); }
.mark__hub-inner { fill: var(--ground); }

@keyframes mark-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Below ~48px the veins drop; the silhouette carries it (§4). */
.mark--small .mark__vein { display: none; }

/* --- Shell ------------------------------------------------------------------ */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 var(--pad) 60px; /* room for the fixed footer */
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
}

/* --- Masthead ----------------------------------------------------------------
   Half the page is empty, and the masthead is the first proof of that: one
   row, generous padding, nothing crowding the mark. */

.masthead {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding-top: 32px;
  padding-bottom: 32px;
}

.masthead__brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.masthead__brand .mark { width: 36px; height: 36px; }

.masthead__titles {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.masthead__name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 22px;
  letter-spacing: -0.01em;
  color: var(--text);
}

.masthead__sub {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 2.2px;
  text-transform: uppercase;
  color: var(--mute);
}

/* The generate button — the signature card (§8): 2px keyline, 11px radius,
   hard 5px offset shadow, no blur. It is the point of the page, so nothing
   else on this page gets the same treatment. Opens the generate sheet as of
   Sprint 5 — the button inside that sheet is the one still inert (Sprint 6). */
.btn-generate {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text);
  background: transparent;
  border: 2px solid var(--lift);
  border-radius: 11px;
  padding: 12px 22px;
  box-shadow: var(--shadow-accent);
  cursor: pointer;
  flex: none;
}

.masthead__right {
  display: flex;
  align-items: center;
  gap: 16px;
}

/* A running job's one-line strip when the sheet is closed — small, at the
   edge, BAMBOO (the machine). Clicking it reopens the sheet. */
.masthead__running {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--bamboo);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}
.masthead__running[hidden] { display: none; }
.masthead__running.is-running { color: var(--bamboo); }
.masthead__running:not(.is-running) { color: var(--lift); } /* waiting on him */
.masthead__running.is-open { text-decoration: underline; }

/* --- The queue ------------------------------------------------------------
   The server's list, not this tab's: what is running, what is behind it, and
   what happened to the last few. Hard edges, one offset shadow, no blur. */

.queuepanel {
  position: absolute;
  top: calc(100% - 18px);
  right: 0;
  z-index: 40;
  width: min(680px, calc(100vw - 2 * var(--pad)));
  max-height: min(70vh, 620px);
  overflow-y: auto;
  background: var(--plate);
  border: 2px solid var(--rule);
  border-radius: 10px;
  box-shadow: var(--shadow);
}

.queuepanel[hidden] { display: none; }

.queuepanel__head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--rule);
}

.queuepanel__title {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.6px;
  color: var(--text);
}

.queuepanel__note {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  color: var(--dim);
}

.queuepanel__clear, .queuepanel__close {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  color: var(--mute);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}

.queuepanel__clear:hover, .queuepanel__close:hover { color: var(--lift); }
.queuepanel__clear[hidden] { display: none; }

.queuepanel__empty, .queuepanel__list {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.1px;
  color: var(--mute);
}

.queuepanel__empty { padding: 24px 16px; }

.qrow {
  display: grid;
  grid-template-columns: 92px 46px 1fr auto auto;
  align-items: baseline;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--rule);
}

.qrow:last-child { border-bottom: none; }

.qrow__status { color: var(--mute); }
.qrow--submitted .qrow__status,
.qrow--running .qrow__status,
.qrow--uploading .qrow__status,
.qrow--downloading .qrow__status,
.qrow--writing .qrow__status,
.qrow--done .qrow__status { color: var(--bamboo); }
.qrow--queued .qrow__status,
.qrow--not_run .qrow__status,
.qrow--interrupted .qrow__status { color: var(--lift); }

.qrow__when, .qrow__cost { color: var(--dim); }
.qrow__model { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.qrow__prompt {
  grid-column: 1 / -1;
  color: var(--dim);
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.qrow__prompt.is-error { color: var(--mute); }

.qrow__btn {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  color: var(--lift);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 5px;
  padding: 3px 8px;
  cursor: pointer;
}

.qrow__btn:hover { border-color: var(--lift); }
.qrow__btn.is-armed { border-color: var(--lift); color: var(--void); background: var(--lift); }
.qrow__btn:disabled { color: var(--dim); border-color: var(--rule); cursor: default; }

@media (max-width: 640px) {
  .queuepanel { width: calc(100vw - 2 * var(--pad)); }
  .qrow { grid-template-columns: 78px 42px 1fr; }
  .qrow__cost, .qrow__actions { grid-column: span 1; }
}

/* --- Empty / no-match states ----------------------------------------------
   Honest, not decorative: they say there is nothing (or nothing matched),
   and stop. No placeholder tile, no demo image, no invented number. */

.state-empty, .state-nomatch {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 10px;
  padding: 96px 0;
}

.empty__label {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--mute);
}

.empty__hint {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--dim);
}

.link-action {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--lift);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

/* --- Filters ----------------------------------------------------------------
   One line of Plex Mono. No pills, no boxes, no underline animation — the
   active entry is just TEXT instead of MUTE. */

.filters {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 16px;
  flex-wrap: wrap;
}

.filters__facets {
  display: flex;
  align-items: center;
  gap: 32px;
  flex-wrap: wrap;
}

.filters__types {
  display: flex;
  align-items: center;
  gap: 18px;
}

/* The provider facet row (sprint 16) — same button as the type facet, shown
   only once a second provider has output, separated by a middot. */
.filters__providers {
  display: flex;
  align-items: center;
  gap: 10px;
}
.filters__providers:empty { display: none; }
.filters__providers .filters__sep { color: var(--rule); }

.filters__type {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.filters__type.is-active { color: var(--text); }

.filters__search {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--text);
  background: none;
  border: none;
  border-bottom: 1px solid var(--rule);
  padding: 4px 2px;
  min-width: 220px;
  max-width: 320px;
}

.filters__search:focus {
  outline: none;
  border-bottom-color: var(--lift);
}

.filters__search::placeholder { color: var(--dim); }

/* --- Gallery / grid -----------------------------------------------------------
   §8's gutters: 8px vertical, 16px horizontal — what makes the eye read down
   a column first. */

.gallery {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  padding-bottom: 40px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  column-gap: 16px;
  row-gap: 8px;
}

.tile {
  display: block;
  width: 100%;
  padding: 0;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.tile__media {
  position: relative;
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: 8px;
  overflow: hidden;
}

.tile:focus-visible .tile__media,
.tile:hover .tile__media {
  border-color: var(--lift);
}

.tile__media img, .tile__media video {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  background: var(--plate);
}

/* A 3D tile before its still exists — the size a still will be, saying what
   it is. Not a spinner: nothing here pretends to measure progress. */
.tile__still {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.4px;
  color: var(--mute);
}

.tile:focus-visible { outline: none; }

.tile__badge {
  position: absolute;
  bottom: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mute);
  background: var(--void);
  border-radius: 5px;
  padding: 3px 7px;
}

.tile__badge--video { left: 6px; }
.tile__badge--duration { right: 6px; }

.tile__caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 2px 0;
}

.tile__model {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tile__model--orphan { color: var(--dim); }

.tile__date {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  color: var(--dim);
  flex: none;
}

.load-more {
  align-self: center;
  margin-top: 28px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 10px 20px;
  cursor: pointer;
}

.load-more:hover { color: var(--text); border-color: var(--mute); }

/* --- The sheet — a workspace, not a narrow drawer ---------------------------
   Full-bleed over the grid: a big stage on the left for the media (or, in
   the generate sheet, honest empty space until Sprint 7 has a result to put
   there), a fixed-width panel of controls on the right — "the workspace",
   in the Captain's own words. Never a centred modal, never a blurred
   backdrop (§13). There is no separate backdrop element any more: the
   stage's own empty background is the click-away-to-close surface, same as
   a lightbox — clicking the media itself never closes it. */

.sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
}

.sheet {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: row;
  background: var(--plate);
}

.sheet:focus { outline: none; }

.sheet__stage {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 10px;
  background: var(--void);
  padding: 48px;
  cursor: default;
}

.sheet__stage img, .sheet__stage video {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  cursor: default;
}

.sheet__model {
  display: block;
  width: 100%;
  flex: 1;
  min-height: 0;
  border-radius: 8px;
  cursor: grab;
  touch-action: none;
}

.sheet__model:active { cursor: grabbing; }

.sheet__model-hint {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.4px;
  color: var(--dim);
}

.sheet__media-fallback {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.6px;
  color: var(--mute);
}

.sheet__panel {
  position: relative;
  width: 460px;
  flex: none;
  height: 100%;
  overflow-y: auto;
  border-left: 2px solid var(--rule);
  box-shadow: -5px 0 0 0 var(--rule);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.sheet__panel-top {
  display: flex;
  justify-content: flex-end;
}

.sheet__close {
  font-family: var(--font-mono);
  font-size: 16px;
  color: var(--mute);
  background: none;
  border: none;
  cursor: pointer;
  line-height: 1;
  padding: 4px;
}

.sheet__close:hover { color: var(--text); }

.sheet__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sheet__label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--mute);
}

.sheet__copy {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.sheet__copy:hover { color: var(--text); }
.sheet__copy.is-copied { color: var(--bamboo); }

.sheet__prompt {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  margin-top: -8px;
}

.sheet__facts {
  display: grid;
  grid-template-columns: auto 1fr;
  row-gap: 8px;
  column-gap: 16px;
  margin: 0;
}

.sheet__facts dt {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mute);
}

.sheet__facts dd {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--text);
  word-break: break-word;
}

.sheet__params-table {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 8px;
}

.sheet__param-row {
  display: flex;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 12px;
}

.sheet__param-key { color: var(--mute); flex: 0 0 40%; }
.sheet__param-value { color: var(--text); word-break: break-word; }

.sheet__actions {
  display: flex;
  gap: 10px;
}

.btn-plain {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 10px 14px;
  cursor: pointer;
  text-align: center;
}

.btn-plain:hover:not(:disabled) { border-color: var(--mute); }
.btn-plain:disabled { color: var(--dim); cursor: not-allowed; }

.sheet__danger {
  border-top: 1px solid var(--rule);
  padding-top: 14px;
  margin-top: auto;
}

.btn-danger {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.btn-danger:hover { color: var(--text); }

.confirm-row__top {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.confirm-row__question {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text);
}

.confirm-row__cancel, .confirm-row__yes {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.confirm-row__cancel { color: var(--mute); }
.confirm-row__cancel:hover { color: var(--text); }
.confirm-row__yes { color: var(--lift); }
.confirm-row__yes:hover { color: var(--text); }

.confirm-row__note {
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--dim);
  word-break: break-word;
}

.sheet__danger-error {
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--lift);
}

@media (max-width: 640px) {
  /* The two-pane workspace stacks: stage on top (shorter, media still
     visible), the control panel full-width below it, independently
     scrollable — there is no room for a 460px side column on a phone. */
  .sheet { flex-direction: column; }
  .sheet__stage { flex: none; height: 38vh; padding: 20px; }
  .sheet__panel { width: 100%; border-left: none; border-top: 2px solid var(--rule); box-shadow: 0 -5px 0 0 var(--rule); }
  .filters { flex-direction: column; align-items: flex-start; }
  .filters__search { max-width: 100%; width: 100%; }
  /* The footer's three glance-numbers stack instead of cramming one line. */
  .footer { flex-wrap: wrap; gap: 2px 14px; font-size: 10px; padding: 8px var(--pad); }

  /* The reference picker gives its margins to the tiles. The head and the
     footer stay put — losing sight of USE is what makes the sheet a dead end. */
  .refpick { padding: 14px; gap: 10px; }
  .refpick__grid { grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 6px; }
  .refpick__use { padding: 8px 14px; }
}


/* --- Footer line ---------------------------------------------------------- */
/* Pinned to the bottom of the window: the spend total and the credit row are
   numbers you glance at, so they must not sink below a growing gallery. The
   shell carries matching bottom padding so the last tiles clear it. */

.footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0 auto;
  width: 100%;
  max-width: var(--shell);
  padding: 12px var(--pad);
  background: var(--ground);
  border-top: 1px solid var(--rule);
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.6px;
  color: var(--dim);
  z-index: 20;
}

.footer--error { color: var(--lift); }

/* The credit row (sprint 13) — glanceable, sits with the spend total. MUTE
   by default; a single figure turns LIFT when it drops below the job ceiling
   (confirm_over), which is the only balance state waiting on the Captain. */
.footer__balances { color: var(--mute); }
.footer__bal { white-space: nowrap; }
.footer__bal.is-low { color: var(--lift); }

/* --- The generate sheet (sprint 5) ------------------------------------------
   Shares the sheet's stage+panel shell exactly (S3's two-pane rework): the
   outer .sheet row layout needs no override here. Its own panel content:
   the picker, the schema-driven form, the request preview. Nothing here
   submits — GENERATE stays inert. */

.gen__panel { gap: 20px; }

.gen__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.gen__title {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text);
}

.gen__loading, .gen__error {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mute);
}
.gen__error { color: var(--lift); text-transform: none; letter-spacing: normal; }
.gen__error code { font-family: var(--font-mono); }

/* Picker */

.gen__picker { display: flex; flex-direction: column; gap: 12px; }

.gen__stale {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  color: var(--lift);
  border: 1px solid var(--lift);
  border-radius: 8px;
  padding: 8px 12px;
}

/* What a refresh brought in. BAMBOO — the machine reporting on work it did,
   not something waiting on the Captain's hand. */
.gen__refresh-note {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  color: var(--bamboo);
  padding: 2px 0;
}

.gen__families {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.gen__family {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.gen__family.is-active { color: var(--text); }

.gen__search-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.gen__search {
  flex: 1;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--text);
  background: none;
  border: none;
  border-bottom: 1px solid var(--rule);
  padding: 4px 2px;
}
.gen__search:focus { outline: none; border-bottom-color: var(--lift); }
.gen__search::placeholder { color: var(--dim); }

.gen__refresh {
  flex: none;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 5px 10px;
  cursor: pointer;
}
.gen__refresh:hover:not(:disabled) { color: var(--text); border-color: var(--mute); }
.gen__refresh.is-stale { color: var(--lift); border-color: var(--lift); }
.gen__refresh.is-busy { color: var(--bamboo); border-color: var(--bamboo); cursor: default; }
.gen__refresh:disabled { cursor: default; }

.gen__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* The shelf is the main view now — use the room the sheet has. */
  max-height: max(46vh, calc(100vh - 250px));
  overflow-y: auto;
}

.gen__list-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--dim);
  padding: 8px 4px 2px;
}

.gen__list-rule { border-top: 1px solid var(--rule); margin: 6px 0; }

.gen__list-empty, .gen__list-more {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--mute);
  text-align: center;
  padding: 16px 0;
}

.gen__row {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid var(--rule);
  padding: 8px 4px;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.gen__row:hover, .gen__row:focus-visible { background: var(--plate); outline: none; }

.gen__row-top, .gen__row-bottom {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.gen__row-label {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--text);
}

.gen__row-vendor {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--dim);
  white-space: nowrap;
}

.gen__row-type {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  color: var(--mute);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gen__row-price {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--mute);
  white-space: nowrap;
}

/* Chosen model summary */

.gen__chosen {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rule);
}

.gen__chosen-info { display: flex; flex-direction: column; gap: 2px; }

.gen__chosen-label {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--text);
}

.gen__chosen-vendor {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--dim);
}

.gen__change {
  flex: none;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: none;
  cursor: pointer;
}
.gen__change:hover { color: var(--text); }

.gen__dropped-note {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--lift);
}

/* RUN ON — the provider chooser (sprint 14). Between the chosen-model summary
   and the form, in the order of the decisions he makes. Selected option is a
   LIFT keyline; the rest are RULE. No transition. */
.gen__runon {
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
}

.gen__runon-label {
  align-self: center;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  color: var(--mute);
  flex: none;
}

.gen__runon-opt {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 10px;
  background: none;
  border: 1px solid var(--rule);
  cursor: pointer;
  text-align: left;
}
.gen__runon-opt:hover { background: var(--plate); }
.gen__runon-opt.is-selected { border-color: var(--lift); }

.gen__runon-name {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--text);
}

.gen__runon-num {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--dim);
}

/* The form — one field per row, built by params.js */

.gen__form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.field { display: flex; flex-direction: column; gap: 4px; }
.field--inline { flex-direction: row; align-items: center; gap: 10px; }

.field__label-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.field__label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mute);
}

.field:focus-within .field__label { color: var(--text); }

.field__required-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--lift);
  flex: none;
}

.field__chip {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--mute);
  border: 1px solid var(--rule);
  border-radius: 5px;
  padding: 1px 5px;
}

.field__description {
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--dim);
  line-height: 1.4;
}

.field__body { display: flex; flex-direction: column; gap: 6px; }
.field--inline .field__body { order: -1; }

.field--prompt .field__textarea { font-size: 14px; }

.field__textarea {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--text);
  background: var(--void);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 10px 12px;
  resize: none; /* auto-grows with content instead — params.js's autoGrow() */
  overflow: hidden;
  line-height: 1.5;
}
.field__textarea:focus { outline: none; border-color: var(--lift); }

.field__segmented {
  display: flex;
  border: 1px solid var(--rule);
  border-radius: 8px;
  overflow: hidden;
  width: fit-content;
}

.field__segment {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--mute);
  background: none;
  border: none;
  border-right: 1px solid var(--rule);
  padding: 6px 12px;
  cursor: pointer;
}
.field__segment:last-child { border-right: none; }
.field__segment.is-active { color: var(--text); box-shadow: inset 0 -2px 0 0 var(--lift); }

.field__select {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text);
  background: var(--void);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 7px 10px;
  width: fit-content;
}
.field__select:focus { outline: none; border-color: var(--lift); }

.field__slider-row { display: flex; align-items: center; gap: 12px; }

.field__slider {
  flex: 1;
  -webkit-appearance: none;
  appearance: none;
  height: 1px;
  background: var(--rule);
}
.field__slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  border-radius: 0;
  background: var(--lift);
  cursor: pointer;
}
.field__slider::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 0;
  border: none;
  background: var(--lift);
  cursor: pointer;
}

.field__readout {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text);
  min-width: 2.5em;
  text-align: right;
}

.field__number-row { display: flex; align-items: center; gap: 10px; }

.field__number, .field__text {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text);
  background: var(--void);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 7px 10px;
}
.field__number { width: 120px; }
.field__text { width: 100%; }
.field__number:focus, .field__text:focus { outline: none; border-color: var(--lift); }

.field__random {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--mute);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 5px 8px;
  cursor: pointer;
}
.field__random:hover { color: var(--text); }

.field__checkbox {
  width: 16px;
  height: 16px;
  flex: none;
  background: none;
  border: 1px solid var(--rule);
  border-radius: 2px;
  cursor: pointer;
  position: relative;
  padding: 0;
}
.field__checkbox.is-checked::before,
.field__checkbox.is-checked::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 10px; height: 1.5px;
  background: var(--lift);
  transform-origin: center;
}
.field__checkbox.is-checked::before { transform: translate(-50%, -50%) rotate(45deg); }
.field__checkbox.is-checked::after { transform: translate(-50%, -50%) rotate(-45deg); }

.field__note {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--dim);
}

/* A field that cannot be used as typed. LIFT, because it is waiting on the
   Captain's hand — no icon, no shake, no colour the system does not have. */
.field__error {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--lift);
  margin-top: 4px;
}
.field__textarea.is-error,
.field__text.is-error { border-color: var(--lift); }

/* One LoRA per row: the link takes the width, the scale is a narrow box
   beside it. Same inputs as everywhere else — nothing new to look at. */
.field__lora-scale { width: 72px; flex: none; }

.field__ref-array { display: flex; flex-direction: column; gap: 6px; }
.field__ref-row { display: flex; align-items: center; gap: 8px; }
.field__ref-row .field__text { flex: 1; }

.field__ref-remove, .field__ref-add {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--mute);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  flex: none;
}
.field__ref-remove:hover, .field__ref-add:hover { color: var(--text); }
.field__ref-add { align-self: flex-start; }

.params__more summary {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mute);
  cursor: pointer;
  padding: 6px 0;
}
.params__more summary:hover { color: var(--text); }
.params__more[open] summary { color: var(--text); }
.params__more { display: flex; flex-direction: column; }
.params__more > *:not(summary) { margin-top: 12px; }

/* Request preview — permanent, not just for this sprint */

.gen__request summary {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mute);
  cursor: pointer;
  padding: 6px 0;
  border-top: 1px solid var(--rule);
}
.gen__request summary:hover { color: var(--text); }
.gen__request[open] summary { color: var(--text); }

.gen__request-json, .gen__request-cli {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.5;
  color: var(--text);
  background: var(--void);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 12px;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 8px 0 0;
}
.gen__request-cli { color: var(--dim); }

/* The cost region — the signature-card button with the price on it, the
   under-line saying where the number came from, and the ceiling confirm. */
.gen__cost {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* The button is the point of the page: 2px keyline, 11px radius, hard 5px
   offset shadow, LIFT — but only once it is actually pressable. Disabled or
   waiting on data, it sits quiet in RULE. */
.btn-generate-sheet {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mute);
  background: transparent;
  border: 2px solid var(--rule);
  border-radius: 11px;
  padding: 12px 22px;
  cursor: not-allowed;
  width: 100%;
}
.btn-generate-sheet.is-ready {
  color: var(--text);
  border-color: var(--lift);
  box-shadow: 5px 5px 0 0 var(--lift);
  cursor: pointer;
}
.btn-generate-sheet[hidden] { display: none; }

.gen__cost-amount { color: var(--mute); }
.btn-generate-sheet.is-ready .gen__cost-amount { color: var(--lift); }
.gen__cost-amount.is-unknown { color: var(--mute); }
.gen__cost-sep { color: var(--rule); }

/* Plex Mono 10px MUTE: the balance, the unit count, the basis. LIFT only
   when it is telling him something needs his hand — missing fields, or a
   balance that will not cover the press. */
.gen__cost-line {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
}
.gen__cost-line[hidden] { display: none; }
.gen__cost-line.is-needs { color: var(--lift); }
.gen__cost-line .is-low { color: var(--lift); }

.gen__cost-topup {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
}

.gen__confirm[hidden] { display: none; }
.gen__confirm .confirm-row__question { color: var(--text); }

/* --- The stage while a job runs / after it lands ------------------------- */

/* RUNNING · M:SS — Plex Mono, one tick per second, BAMBOO. The elapsed
   counter is the whole animation: no spinner, no bar, no shimmer. */
.gen__stage-run {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--bamboo);
  font-variant-numeric: tabular-nums;
}

/* DONE · 0:12 · $0.01 — sits under the result, same colour. */
.gen__stage-line {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--bamboo);
}

.sheet__stage--media { padding: 32px; }

/* The provider's message, verbatim, in a keylined block — LIFT, because it
   is waiting on his hand. */
.gen__stage-error {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--lift);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 14px 16px;
  max-width: 460px;
  white-space: pre-wrap;
  word-break: break-word;
}
.gen__retry {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--lift);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}

/* A just-generated tile, until the sheet closes. */
.tile__new {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  color: var(--bamboo);
  margin-left: auto;
}

/* --- The reference control (Sprint 8) ----------------------------------- */

.field__ref-count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  color: var(--mute);
}

.ref-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.ref-cell {
  position: relative;
  width: 84px;
  height: 84px;
  border: 1px solid var(--rule);
  background: var(--void);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.ref-cell.is-error { border-color: var(--lift); }
.ref-cell img, .ref-cell video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ref-cell__status {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--bamboo);
  text-align: center;
  padding: 4px;
}
.ref-cell.is-error .ref-cell__status { color: var(--lift); }
.ref-cell__order {
  position: absolute;
  top: 2px;
  left: 2px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--lift);
  background: var(--void);
  padding: 0 3px;
}
.ref-cell__remove {
  position: absolute;
  top: 2px;
  right: 2px;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1;
  color: var(--mute);
  background: var(--void);
  border: none;
  padding: 2px 3px;
  cursor: pointer;
}
.ref-cell__remove:hover { color: var(--lift); }
.ref-cell__move {
  position: absolute;
  bottom: 2px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--mute);
  background: var(--void);
  border: none;
  padding: 0 3px;
  cursor: pointer;
}
.ref-cell__move:hover { color: var(--lift); }
.ref-cell__move:first-of-type { left: 2px; }
.ref-cell__move:last-of-type { right: 2px; }

.ref-slot {
  width: 84px;
  height: 84px;
  border: 1px dashed var(--rule);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px;
  text-align: center;
}
.ref-slot.is-over { border-color: var(--lift); }
.ref-slot__hint {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--mute);
}
.ref-slot__actions {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ref-slot__sep { display: none; }
.ref-slot__btn {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--mute);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}
.ref-slot__btn:hover { color: var(--lift); }

.ref-err { color: var(--lift) !important; }

.gen__ref-hint {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--mute);
  padding: 4px 0 8px;
}

/* --- The reference picker (Sprint 8 §4) ------------------------------- */

/* The sheet itself does not scroll — the grid inside it does. Scrolling the
   whole sheet let the grid grow past the viewport and carried the footer,
   and the USE button in it, off the bottom of a short screen with nothing to
   say so. Head, search and footer are fixed; only the tiles move. */
.refpick {
  flex-direction: column;
  padding: 24px;
  gap: 14px;
  overflow: hidden;
}
.refpick__head,
.refpick__search,
.refpick__foot { flex: none; }
.refpick__head {
  display: flex;
  align-items: baseline;
  gap: 14px;
}
.refpick__title {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text);
}
.refpick__only {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  color: var(--mute);
}
.refpick__head .sheet__close { margin-left: auto; }
.refpick__search {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text);
  background: var(--void);
  border: none;
  border-bottom: 1px solid var(--rule);
  padding: 8px 0;
  width: 100%;
}
.refpick__search::placeholder { color: var(--dim); }
.refpick__search:focus { outline: none; border-bottom-color: var(--lift); }
.refpick__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px;
  align-content: start;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.refpick__grid .tile { width: 100%; }
.refpick-cell { position: relative; cursor: pointer; }
.refpick-cell.is-picked { outline: 2px solid var(--lift); outline-offset: -2px; }
.refpick-cell__n {
  position: absolute;
  top: 4px;
  left: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--lift);
  background: var(--void);
  padding: 0 4px;
  z-index: 1;
}
.refpick__empty {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  color: var(--mute);
  padding: 24px 0;
}
.refpick__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--rule);
  padding-top: 12px;
}
.refpick__count {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  color: var(--mute);
}
.refpick__use {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--lift);
  background: transparent;
  border: 2px solid var(--lift);
  border-radius: 11px;
  padding: 8px 18px;
  cursor: pointer;
}
.refpick__use:disabled { color: var(--dim); border-color: var(--rule); cursor: not-allowed; }

/* A short window — a laptop with the browser not maximised, a split screen.
   The grid keeps a floor to stand on so the footer is always reachable; the
   head loses its padding first. */
@media (max-height: 560px) {
  .refpick { padding: 12px 16px; gap: 8px; }
  .refpick__grid { grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); min-height: 60px; }
  .refpick__search { padding: 5px 0; }
  .refpick__foot { padding-top: 8px; }
}


/* --- Small screens ---------------------------------------------------------- */

@media (max-width: 640px) {
  :root { --pad: 16px; }
  .masthead { flex-wrap: wrap; padding-top: 20px; padding-bottom: 20px; }
  .masthead__name { font-size: 19px; }
}

/* --- Login (Sprint 21) ------------------------------------------------------
   The one page served before the lock opens. Same parts as the rest of the
   app: the mark, the wordmark, one hairline field, the LIFT button. */
.login {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 24px var(--pad);
}

.login__form {
  display: flex;
  flex-direction: column;
  gap: 18px;
  width: 100%;
  max-width: 320px;
  margin-top: 12px;
}

.login__input {
  font-family: var(--font-sans);
  font-size: 16px; /* 16 keeps iOS from zooming on focus */
  color: var(--text);
  background: none;
  border: none;
  border-bottom: 1px solid var(--rule);
  padding: 6px 2px;
}

.login__input:focus {
  outline: none;
  border-bottom-color: var(--lift);
}

.login__error {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--lift);
}

/* --- The shelf (Sprint 23) --------------------------------------------------
   His models in the picker: the catalog's row, plus a cost line underneath and
   a REMOVE that asks once. No new motion. */
.gen__mode {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 0 8px;
}

.gen__mode-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.6px;
  color: var(--mute);
}

.gen__shelf-item { border-bottom: 1px solid var(--rule); }
.gen__shelf-item .gen__row { border-bottom: none; padding-bottom: 2px; }
.gen__shelf-item.is-missing .gen__row { cursor: default; }
.gen__shelf-item.is-missing .gen__row:hover { background: none; }
.gen__shelf-item.is-missing .gen__row-label { color: var(--mute); }

.gen__row-cost {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  color: var(--dim);
  padding-top: 3px;
}
.gen__row-cost.is-unknown { color: var(--mute); }

.gen__shelf-actions {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 14px;
  padding: 0 4px 8px;
}

.gen__shelf-remove {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--dim);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.gen__shelf-remove:hover { color: var(--lift); }

/* --- Consent (Sprint 24) — the page an agent's connection request lands on --- */
.consent__who { margin: 0; font-family: var(--font-sans); font-size: 15px; color: var(--text); }
.consent__can { margin: 0; padding-left: 18px; font-family: var(--font-sans); font-size: 13px; color: var(--mute); }
.consent__can li { margin: 4px 0; }
.consent__can strong { color: var(--lift); font-weight: 400; }
.consent__note { margin: 0; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.6px; color: var(--dim); }
.consent__note code { color: var(--mute); }

/* =============================================================================
   The phone layer (Sprint 26)
   Built to docs/plan/prototype/phone.html. The desktop layout above is left as it
   was: everything that changes is inside the narrow-screen query, and the parts
   that only make sense on a phone are hidden everywhere else.

   Motion here is the fourteen in docs/plan/built/README.md — instant, following a
   finger 1:1, or steps(). Nothing fades, blurs or eases (design-system §13).
   ========================================================================== */

/* Present at every width, shown only on a phone. */
.filters__phone, .dock, .sheet__bar, .sheet__quick, .pull, .tile__tick { display: none; }
.toast[hidden] { display: none; }
.sheet__ghost { display: none; }

/* A button presses into its shadow: 4px, instant, back the moment the finger lifts. */
.btn-generate:active { transform: translate(4px, 4px); box-shadow: 1px 1px 0 0 var(--lift); }
.btn-generate-sheet.is-ready:active { transform: translate(4px, 4px); }

/* The mark turns fast while the gallery loads: real work, not a spinner (once per 2.4s). */
.is-loading .mark--small .mark__rotor { animation-duration: 2.4s; }

.toast {
  position: fixed;
  left: var(--pad);
  right: var(--pad);
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  pointer-events: none;                 /* a toast never catches a touch */
  background: var(--plate);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--bamboo);
  padding: 10px 12px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--text);
}

.btn-plain--danger { color: var(--lift); border-color: var(--lift); }

@media (max-width: 640px) {
  :root { --pad: 12px; }
  body { overscroll-behavior-y: contain; }
  /* 16px keeps iOS from zooming the page when a field takes focus. It has to beat
     each field's own font-size, hence !important — on a phone only. */
  input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]), textarea, select { font-size: 16px !important; }

  /* --- masthead: the name, and — only when something runs — its strip ---------- */
  .shell { padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px)); }
  .masthead { flex-wrap: wrap; row-gap: 8px; padding-top: calc(10px + env(safe-area-inset-top, 0px)); padding-bottom: 6px; }
  .masthead__brand .mark { width: 30px; height: 30px; }
  .masthead__name { font-size: 18px; }
  .masthead__sub { display: none; }
  #masthead-generate { display: none; }          /* the dock has it, under the thumb */
  .masthead__right { display: contents; }
  .masthead__running {
    order: 3; flex: 1 1 100%;
    display: block; text-align: left;
    padding: 11px 12px;
    background: var(--plate);
    border-block: 1px solid var(--rule);
    border-left: 3px solid var(--bamboo);
    min-height: 44px;
  }
  .masthead__running:not(.is-running) { border-left-color: var(--lift); }

  /* --- filters: one row that scrolls sideways; search on demand ---------------- */
  .filters { flex-direction: column; align-items: stretch; flex-wrap: nowrap; gap: 0; padding-bottom: 8px; }
  .filters__facets {
    flex-wrap: nowrap; gap: 20px; overflow-x: auto; scrollbar-width: none;
    margin-inline: calc(-1 * var(--pad)); padding-inline: var(--pad);
  }
  .filters__facets::-webkit-scrollbar { display: none; }
  .filters__types, .filters__providers { flex: none; flex-wrap: nowrap; white-space: nowrap; word-break: normal; }
  .filters__type { padding: 14px 0; min-height: 44px; white-space: nowrap; }
  .filters__phone { display: inline-flex; align-items: center; }
  .filters__search { display: none; }
  .filters.is-searching .filters__search { display: block; max-width: none; width: 100%; padding: 10px 2px; }

  /* --- the gallery: the point of the page. Two columns, small gutters ---------- */
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 8px; row-gap: 8px; align-items: start; }
  .tile { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
  .tile__caption { padding-top: 4px; }
  .footer { position: static; margin-top: 20px; }

  /* pull to refresh: the page follows the finger, then goes back instantly */
  .pull { display: flex; height: 0; overflow: hidden; align-items: flex-end; justify-content: center; }
  .pull__text { padding-bottom: 8px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--mute); }

  /* --- select mode ------------------------------------------------------------- */
  .grid.is-selecting .tile__tick {
    display: grid; position: absolute; top: 6px; right: 6px; width: 26px; height: 26px; place-items: center;
    border-radius: 3px; font-family: var(--font-mono); font-size: 14px;
    background: var(--void); color: var(--void); box-shadow: inset 0 0 0 2px var(--mute);
  }
  .tile.is-selected .tile__tick { background: var(--lift); color: var(--void); box-shadow: none; }
  .tile.is-selected .tile__media { border-color: var(--lift); }
  .tile.is-selected .tile__media::after {
    content: ''; position: absolute; inset: 0; border: 3px solid var(--lift); border-radius: 7px; pointer-events: none;
  }

  /* --- the dock: Generate under the thumb, or what to do with the selection ----- */
  .dock {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 15;
    gap: 12px; align-items: center;
    padding: 10px var(--pad) calc(12px + env(safe-area-inset-bottom, 0px));
    background: var(--ground); border-top: 1px solid var(--rule);
  }
  .dock__generate { flex: 1; min-height: 50px; }
  .dock__select { display: flex; flex: 1; align-items: center; gap: 10px; }
  .dock__count { flex: 1; font-family: var(--font-mono); font-size: 12px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--text); }
  .dock .btn-plain { flex: none; min-height: 46px; padding: 10px 16px; }
  .dock__confirm { flex: 1; }
  .dock__confirm .confirm-row__top { min-height: 46px; align-items: center; }
  .dock__confirm .confirm-row__cancel, .dock__confirm .confirm-row__yes { padding: 12px 8px; }

  /* --- the picture: it takes the whole screen ---------------------------------- */
  .sheet { flex-direction: column; padding-top: env(safe-area-inset-top, 0px); }
  .sheet__bar {
    display: flex; align-items: center; justify-content: space-between; gap: 6px;
    padding: 4px 6px; min-height: 52px; background: var(--void);
  }
  .sheet__barbtn {
    min-width: 44px; min-height: 44px; background: none; border: none; cursor: pointer;
    color: var(--text); font-family: var(--font-mono); font-size: 20px; line-height: 1;
  }
  .sheet__barbtn:disabled { color: var(--dim); cursor: default; }
  .sheet__nav { display: flex; align-items: center; }
  .sheet__count { min-width: 74px; text-align: center; font-family: var(--font-mono); font-size: 11px; letter-spacing: 1.4px; color: var(--mute); }
  .sheet__by { min-width: 64px; text-align: right; padding-right: 8px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--bamboo); }

  .sheet__stage { flex: 1; height: auto; min-height: 0; padding: 4px 8px; position: relative; overflow: hidden; touch-action: none; }
  .sheet__stage img { -webkit-user-select: none; user-select: none; -webkit-user-drag: none; }
  .sheet__ghost {
    display: flex; position: absolute; top: 0; width: 100%; height: 100%; padding: 4px 8px;
    align-items: center; justify-content: center; pointer-events: none;
    font-family: var(--font-mono); font-size: 11px; letter-spacing: 1.4px; color: var(--dim);
  }
  .sheet__ghost img { max-width: 100%; max-height: 100%; object-fit: contain; }
  .sheet__stage img.is-snap, .sheet__ghost.is-snap { transition: transform 120ms steps(4); }

  .sheet__panel {
    width: 100%; height: auto; flex: none; max-height: 64vh; overflow-y: auto;
    border-left: none; border-top: 2px solid var(--rule); box-shadow: 0 -5px 0 0 var(--rule);
    padding: 10px var(--pad) calc(12px + env(safe-area-inset-bottom, 0px)); gap: 12px;
  }
  .sheet__quick { display: flex; gap: 8px; }
  .sheet__quick > * {
    flex: 1; min-width: 0; min-height: 46px; padding: 10px 4px;
    display: inline-flex; align-items: center; justify-content: center; text-decoration: none; font-size: 11px;
  }
  /* collapsed: just the quick row — everything else waits behind DETAILS */
  .sheet__panel-top { display: none; }
  .sheet:not(.is-details) .sheet__row,
  .sheet:not(.is-details) .sheet__prompt,
  .sheet:not(.is-details) .sheet__facts,
  .sheet:not(.is-details) .sheet__params,
  .sheet:not(.is-details) .sheet__actions { display: none; }
  .sheet__danger #sheet-delete { display: none; }   /* the quick row's DELETE is the one */
  .sheet__actions .btn-plain { min-height: 46px; }
}

/* Reduced motion: everything appears in place. */
@media (prefers-reduced-motion: reduce) {
  .mark__rotor { animation: none; }
  *, *::before, *::after { animation-duration: 0s !important; transition-duration: 0s !important; }
}

/* --- The generate sheet on a phone: short, so the pictures stay in view ------------ */
.gen__edit, .gen__grip, .gen__holdbar { display: none; }

@keyframes gen-rise { from { transform: translateY(100%); } to { transform: none; } }

@media (max-width: 640px) {
  /* A bottom sheet, not a screen. The gallery above it stays on screen; a tap on it closes the sheet. */
  #generate-overlay { background: transparent; }
  #generate-overlay .sheet.gen {
    top: auto; height: auto; max-height: 66vh; flex-direction: column; padding-top: 0;
    border-top: 2px solid var(--mute); box-shadow: none;
  }
  #generate-overlay:not([hidden]) .sheet.gen { animation: gen-rise 150ms steps(5) both; }   /* steps(5), 150ms */
  .gen .sheet__stage.is-idle { display: none; }                                              /* no empty stage */
  .gen .sheet__stage { flex: none; height: auto; max-height: 34vh; padding: 10px var(--pad); touch-action: auto; }
  .gen .gen__panel {
    flex: 1 1 auto; min-height: 0; width: 100%; height: auto; max-height: none; overflow-y: auto;
    border: none; box-shadow: none; gap: 12px;
    padding: 0 var(--pad) calc(16px + env(safe-area-inset-bottom, 0px));
  }
  .gen__header { position: relative; min-height: 52px; padding-top: 14px; touch-action: none; }
  .gen__header::before {                       /* the handle: drag the sheet down to close it */
    content: ''; position: absolute; top: 5px; left: 50%; width: 40px; height: 4px;
    margin-left: -20px; background: var(--rule);
  }
  .gen__header .sheet__close { min-width: 44px; min-height: 44px; font-size: 18px; }

  /* the shelf: a row of cards you scroll sideways */
  .gen__edit { display: inline; }
  .gen__mode { min-height: 44px; align-items: center; }
  .gen__list.gen__list--shelf {
    flex-direction: row; gap: 8px; max-height: none; overflow-x: auto; overflow-y: hidden;
    padding: 2px 2px 8px; margin-inline: -2px; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .gen__list--shelf::-webkit-scrollbar { display: none; }
  .gen__list--shelf .gen__shelf-item {
    position: relative; flex: none; width: 176px; background: var(--void);
    border: 1px solid var(--rule); border-radius: 8px;
  }
  .gen__list--shelf .gen__row { padding: 10px 10px 4px; border-bottom: none; min-height: 44px; }
  .gen__list--shelf .gen__row-top { flex-direction: column; align-items: flex-start; gap: 2px; }
  .gen__list--shelf .gen__row-label { font-size: 13px; font-weight: 600; }
  .gen__list--shelf .gen__row-type, .gen__list--shelf .gen__row-cost {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; max-width: 100%;
  }
  .gen__list--shelf .gen__shelf-actions { display: none; padding: 0 10px 8px; }
  .gen__list--shelf.is-editing .gen__shelf-actions { display: flex; }
  .gen__list--shelf.is-editing .gen__shelf-remove { min-height: 44px; padding: 0 6px; }
  .gen__grip {
    position: absolute; top: 0; right: 0; width: 44px; height: 44px; display: none; place-items: center;
    font-family: var(--font-mono); font-size: 18px; color: var(--mute); touch-action: none; cursor: grab;
  }
  .gen__list--shelf.is-editing .gen__grip { display: grid; }
  .gen__list--shelf .gen__shelf-item.is-lifted { border: 2px solid var(--lift); box-shadow: 5px 5px 0 0 var(--rule); z-index: 3; }

  /* hold to agree: the YES becomes a hold, and six squares fill under it */
  .gen__confirm .confirm-row__yes { min-height: 46px; padding: 0 12px; touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
  .gen__confirm .confirm-row__cancel { min-height: 46px; padding: 0 12px; }
  .gen__holdbar { display: flex; gap: 3px; padding-top: 4px; }
  .gen__holdbar i { flex: 1; height: 6px; background: var(--rule); }
  .gen__holdbar i.f { background: var(--lift); }
  .gen__confirm:not([hidden]) { padding-bottom: 6px; }

  .gen__search, .gen__cost .btn-generate-sheet { min-height: 46px; }
  .gen__change, .gen__family, .gen__refresh { min-height: 44px; }
}

@media (max-width: 640px) { #generate-sheet.is-snap { transition: transform 120ms steps(4); } }

/* The cost button stays pinned to the bottom of the sheet while the form scrolls. */
@media (max-width: 640px) {
  .gen__cost {
    position: sticky; bottom: 0; z-index: 2; background: var(--plate);
    border-top: 1px solid var(--rule); padding-top: 10px; margin-top: 4px;
  }
}

/* Tighter: the sheet is a strip of controls, not a page. */
@media (max-width: 640px) {
  .gen .gen__panel { gap: 8px; padding-bottom: 0; }
  .gen__header { min-height: 44px; padding-top: 12px; }
  .gen__picker { gap: 2px; }
  .gen__mode { margin: 0; min-height: 40px; }
  .gen__search-row { gap: 8px; }
  .gen__search { min-height: 44px; padding: 6px 2px; }
  /* the pinned cost bar also carries the bottom padding, so nothing shows through under it */
  .gen__cost { padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
}

/* SEARCH and SELECT stay pinned at the right edge while the filters scroll sideways. */
.filters__phonewrap { display: none; }
@media (max-width: 640px) {
  .filters__phonewrap {
    display: flex; flex: none; gap: 16px; margin-left: auto; padding-left: 14px;
    position: sticky; right: 0; background: var(--ground); border-left: 1px solid var(--rule);
  }
}
