/* App shell.
 *
 * One layout, two shapes. On a phone the nav is a bottom bar sitting
 * above the home indicator; on a desktop the same nav becomes a left
 * rail. It is the same markup and the same state -- there is no mobile
 * build and no desktop build, which is the only way the two stay in
 * sync. */

.app {
  display: grid;
  height: 100dvh;                  /* dvh, not vh: vh is wrong while iOS
                                    * Safari's toolbar is collapsing */
  grid-template-rows: auto 1fr auto;
  grid-template-areas: "top" "main" "nav";
}

/* ---------- top bar ---------------------------------------------- */
/* The shared .appbar (base.css) sits in the grid's top row, across the
   rail and the content on desktop, so it is the same bar as the landing
   page's and not a second, narrower one. */
.app > .appbar { grid-area: top; position: relative; z-index: 20; }

/* ---------- main ------------------------------------------------- */
.main { grid-area: main; position: relative; overflow: hidden; }

.pane {
  position: absolute; inset: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: var(--s-5) max(var(--gutter), var(--safe-r)) var(--s-8) max(var(--gutter), var(--safe-l));
}
.pane[hidden] { display: none; }
.pane-inner { max-width: 940px; margin: 0 auto; }

/* ---------- bottom nav (phone) ------------------------------------ */
.nav {
  grid-area: nav;
  display: flex;
  align-items: stretch;
  padding-bottom: var(--safe-b);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--line);
  z-index: 20;
}
.nav-btn {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  min-height: 54px;
  padding: var(--s-2) 0;
  border: 0; background: none;
  color: var(--ink-3);
  font-size: 10px; font-weight: 600; letter-spacing: .03em;
  cursor: pointer;
  position: relative;
  transition: color var(--dur-1) var(--ease);
}
.nav-btn svg { width: 22px; height: 22px; stroke-width: 1.8; }
.nav-btn[aria-current="page"] { color: var(--accent); }
.nav-btn:disabled { opacity: .3; cursor: not-allowed; }
.nav-btn .dot {
  position: absolute; top: 8px; right: 50%; translate: 16px 0;
  width: 6px; height: 6px; border-radius: var(--r-full); background: var(--accent);
}

/* ---------- desktop: nav becomes a rail --------------------------- */
@media (min-width: 860px) {
  .app {
    grid-template-columns: var(--rail) 1fr;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "top top"
      "nav main";
  }
  .nav {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: var(--s-1);
    padding: calc(var(--safe-t) + var(--s-4)) var(--s-3) var(--s-4);
    border-top: 0;
    border-right: 1px solid var(--line);
    background: var(--surface);
    backdrop-filter: none;
  }
  .nav-btn {
    flex: none;
    flex-direction: row;
    justify-content: flex-start;
    gap: var(--s-3);
    min-height: var(--tap);
    padding: 0 var(--s-3);
    border-radius: var(--r-md);
    font-size: var(--t-base);
    letter-spacing: 0;
  }
  .nav-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
  .nav-btn[aria-current="page"] { background: var(--accent-wash); color: var(--accent); }
  .nav-btn .dot { position: static; translate: none; margin-left: auto; }
  .nav-rail-head { display: block; padding: var(--s-2) var(--s-3) var(--s-4); }
  .nav-sep { display: block; height: 1px; background: var(--line); margin: var(--s-3) var(--s-2); }
  .nav .nav-btn .step-n { display: grid; }
  .nav .nav-btn svg { display: none; }
  .pane { padding: var(--s-6) var(--s-6) var(--s-8); }
}
.nav-rail-head, .nav-sep { display: none; }

/* Step numbers on the rail: a small ring that fills in when the step is
   done, so the rail reads as a checklist of the pipeline. On the phone
   bar the icon stays and the number is dropped; on the rail the number
   replaces the icon. */
.nav-btn .step-n {
  display: none; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: var(--r-full);
  border: 1.5px solid currentColor; font-size: 11px; font-weight: 700;
}
.nav-btn.is-done .step-n { background: var(--ok); border-color: var(--ok); color: #fff; }
.nav-btn.is-done .step-n::before { content: '\2713'; }
.nav-btn.is-done .step-n span { display: none; }

/* ---------- a pane's head and foot: the walkthrough ---------------- */
.pane-head { margin-bottom: var(--s-5); }
.pane-head h1 { font-size: var(--t-lg); margin-top: var(--s-1); }
.pane-head .lede { color: var(--ink-2); margin-top: var(--s-2); max-width: 60ch; }
.pane-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3);
  margin-top: var(--s-7); padding-top: var(--s-5);
  border-top: 1px solid var(--line);
}
.pane-foot .grow { flex: 1; }
/* The way on, at the top of the step and staying there as it scrolls. */
.pane-next {
  position: sticky; top: 0; z-index: 5; position: -webkit-sticky;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3);
  padding: var(--s-3) 0; margin: 0 0 var(--s-5);
  background: var(--bg); border-bottom: 1px solid var(--line);
}
.pane-next .grow { flex: 1; }
/* The bar's own progress line, along its bottom edge: the sort and
   cut when the booth is left, a listing being read, a run. */
.app-progress { position: absolute; left: 0; right: 0; bottom: -1px; height: 6px; background: var(--accent-wash); overflow: hidden; }
.app-progress[hidden] { display: none; }
.app-progress > div { height: 100%; width: 0; background: var(--accent); transition: width .25s var(--ease); box-shadow: 0 0 8px var(--accent); }
.app-progress.is-indeterminate > div { width: 30%; animation: slide 1.1s ease-in-out infinite; }
.appbar-icon { padding: 0 var(--s-2); }
.appbar-icon svg { width: 20px; height: 20px; }
.appbar-status { flex: 1; min-width: 0; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent); font-weight: 600; }
@media (min-width: 620px) { #appStatus { max-width: 40vw; } }
.appbar-actions { min-width: 0; }
.appbar { position: sticky; }
@keyframes slide { from { transform: translateX(-100%); } to { transform: translateX(400%); } }
.pane-next { position: sticky; }
.small.is-ok { color: var(--ok); } .small.is-err { color: var(--err); }
.spin { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line-2); border-top-color: var(--accent); animation: spin .8s linear infinite; display: inline-block; }
.spin[hidden] { display: none; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- drop zone --------------------------------------------- */
.dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-4);
  min-height: 210px;
  padding: var(--s-6) var(--s-5);
  border: 1.5px dashed var(--line-2);
  border-radius: var(--r-xl);
  background: var(--surface);
  text-align: center;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}
.dropzone.is-over { border-color: var(--accent); background: var(--accent-wash); }
/* Once photos are in, the zone is one row: the ways to add more, and
   still the place to drop or paste. */
.dropzone.has-photos {
  flex-direction: row; flex-wrap: wrap; justify-content: flex-start; align-items: center;
  gap: var(--s-2) var(--s-3); min-height: 0; padding: var(--s-3) var(--s-4); margin-bottom: var(--s-5);
  text-align: left;
}
.dropzone.has-photos > svg, .dropzone.has-photos > div:not(.source-actions):not(.source-more), .dropzone.has-photos > p { display: none; }
.dropzone.has-photos .source-actions { display: flex; width: auto; max-width: none; gap: var(--s-2); }
.dropzone.has-photos .source-actions .btn { min-height: 36px; padding: 0 var(--s-4); font-size: var(--t-sm); }
.dropzone.has-photos .source-more { justify-content: flex-start; }
.dropzone svg { width: 40px; height: 40px; color: var(--ink-3); stroke-width: 1.4; }

.source-actions { display: grid; gap: var(--s-3); grid-template-columns: 1fr; width: 100%; max-width: 330px; }
@media (min-width: 560px) { .source-actions { grid-template-columns: 1fr 1fr; max-width: 460px; } }
.source-actions:has(> .hidden:only-of-type), .source-actions:has(> :nth-child(2).hidden) { grid-template-columns: 1fr; max-width: 330px; }
.source-more { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); }

/* ---------- photo grid -------------------------------------------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--s-3);
}
@media (min-width: 640px) { .grid { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--s-4); } }
/* Once photos are in, the grid is one scrolling strip so the vehicle
   fields sit a glance below; a tile opens the lightbox. */
.grid.is-strip {
  display: flex; gap: var(--s-2); overflow-x: auto; padding-bottom: var(--s-2);
  scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
}
.grid.is-strip .tile { flex: 0 0 96px; width: 96px; scroll-snap-align: start; }
/* On a strip thumbnail the tag sits along the bottom, clear of the
   remove button in the top corner. */
/* The tag is the button that corrects the sort, so it is never cut
   short: it sits under the thumbnail as a caption the tile's width. */
.grid.is-strip { padding-bottom: 26px; }
.grid.is-strip .tile-tag { top: 100%; bottom: auto; left: 0; right: 0; margin-top: 3px; font-size: 9px; padding: 2px 4px; border-radius: var(--r-sm); text-align: center; background: var(--sunken); color: var(--ink-2); backdrop-filter: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.grid.is-strip .scene-menu { top: 100%; margin-top: 2px; }
.grid.is-strip .tile-x { width: 22px; height: 22px; font-size: 12px; }
/* A finger gets a hit area past the drawn circle. */
.tile-x::after, .fmt-check::after { content: ''; position: absolute; inset: -8px; }
.fmt-check { position: relative; }

.tile {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--sunken);
  border: 1px solid var(--line);
  cursor: pointer;
  /* Contain paint so a grid of 40 tiles does not force whole-page
   * repaints while results stream in. */
  contain: paint;
}
.tile img, .tile canvas { width: 100%; height: 100%; object-fit: cover; }
.tile.is-pending img { opacity: .38; filter: grayscale(1); }
.tile.is-working::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 20%, var(--accent-wash) 50%, transparent 80%);
  background-size: 220% 100%;
  animation: sweep 1.3s linear infinite;
}
@keyframes sweep { from { background-position: 180% 0; } to { background-position: -80% 0; } }

/* Top-left, not bottom-left: a still's own title and price sit in a
   bottom corner and the tag was covering them. */
.tile-tag {
  position: absolute; left: var(--s-2); top: var(--s-2);
  padding: 2px var(--s-2);
  border-radius: var(--r-full);
  background: rgba(0,0,0,.66);
  backdrop-filter: blur(8px);
  color: #fff;
  font-size: 10px; font-weight: 650; letter-spacing: .02em;
}
/* A result tile: the tag is a caption strip under the picture, since a
   still's own title, badge and line can sit in any corner and a chip
   over the image would cover one of them. */
.tile.is-captioned { aspect-ratio: auto; display: flex; flex-direction: column; }
.tile.is-captioned .tile-pic { position: relative; width: 100%; }
.tile.is-captioned .tile-pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tile.is-captioned .tile-tag {
  position: static; border-radius: 0; backdrop-filter: none;
  background: var(--sunken); color: var(--ink-3);
  padding: 4px var(--s-2); font-size: 10px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tile-tag-btn { cursor: pointer; border: 0; }
.tile-tag-btn.is-user { background: var(--accent); color: #000; }
.scene-menu {
  position: absolute; left: var(--s-2); top: 30px; z-index: 6;
  display: flex; flex-direction: column; gap: 2px; padding: 4px;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-md);
  box-shadow: 0 8px 24px rgba(0,0,0,.4);
}
.scene-choice { border: 0; background: transparent; color: var(--ink); text-align: left; padding: 6px 10px; border-radius: var(--r-sm); font-size: var(--t-sm); cursor: pointer; white-space: nowrap; }
.scene-choice:hover { background: var(--surface-2); }
.scene-choice[aria-pressed="true"] { color: var(--accent); font-weight: 650; }
.grid.is-strip .tile { overflow: visible; contain: none; }
.grid.is-strip .tile img { border-radius: var(--r-md); }
.tile-x {
  position: absolute; top: var(--s-2); right: var(--s-2);
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border: 0; border-radius: var(--r-full);
  background: rgba(0,0,0,.6); color: #fff;
  cursor: pointer; font-size: 14px; line-height: 1;
}

/* ---------- progress ---------------------------------------------- */
.bar { height: 5px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.bar > i {
  display: block; height: 100%; width: 0;
  background: var(--accent);
  border-radius: inherit;
  transition: width var(--dur-2) var(--ease);
}

.stage-list { display: flex; flex-direction: column; gap: var(--s-3); }
.stage {
  display: grid; grid-template-columns: 22px 1fr auto; align-items: center; gap: var(--s-3);
  font-size: var(--t-sm);
}
.stage .mark {
  width: 22px; height: 22px; border-radius: var(--r-full);
  display: grid; place-items: center;
  background: var(--surface-3); color: var(--ink-3);
  font-size: 11px; font-weight: 700;
}
.stage.done .mark { background: rgba(75,168,113,.16); color: var(--ok); }
.stage.active .mark { background: var(--accent-wash); color: var(--accent); }

/* ---------- sheet (mobile) / dialog (desktop) --------------------- */
.sheet {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(0,0,0,.5);
  animation: fade var(--dur-2) var(--ease);
}
.sheet[hidden] { display: none; }
@keyframes fade { from { opacity: 0; } }
.sheet-body {
  width: 100%; max-width: 560px;
  max-height: 88dvh;
  display: flex; flex-direction: column;
  background: var(--surface);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  border: 1px solid var(--line);
  border-bottom: 0;
  padding-bottom: var(--safe-b);
  animation: rise var(--dur-3) var(--ease);
}
@keyframes rise { from { transform: translateY(100%); } }
.sheet-grip {
  width: 36px; height: 4px; border-radius: var(--r-full);
  background: var(--line-2);
  margin: var(--s-3) auto var(--s-1);
  flex: none;
}
.sheet-head {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--line);
  flex: none;
}
.sheet-content { padding: var(--s-5); overflow-y: auto; overscroll-behavior: contain; }
.sheet-foot {
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--line);
  display: flex; gap: var(--s-3);
  flex: none;
}
.sheet-foot .btn { flex: 1; }

@media (min-width: 860px) {
  .sheet { align-items: center; }
  .sheet-body { border-radius: var(--r-xl); border-bottom: 1px solid var(--line); animation: pop var(--dur-2) var(--ease); }
  .sheet-grip { display: none; }
  @keyframes pop { from { transform: scale(.96); opacity: 0; } }
}

/* ---------- misc -------------------------------------------------- */
.form-grid { display: grid; gap: var(--s-4); grid-template-columns: 1fr; }
@media (min-width: 560px) { .form-grid { grid-template-columns: 1fr 1fr; } }
.form-grid .span-2 { grid-column: 1 / -1; }

.banner {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  background: var(--accent-wash);
  border: 1px solid var(--accent-line);
  font-size: var(--t-sm);
}
.banner-err { background: var(--err-wash); border-color: var(--err); }
.banner-warn { background: var(--sunken); border-color: var(--line-2); color: var(--ink-2); }
#warnBox .banner + .banner { margin-top: var(--s-2); }

.empty { text-align: center; padding: var(--s-8) var(--s-5); color: var(--ink-3); }

.copybox {
  position: relative;
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s-4);
  font-size: var(--t-sm);
  white-space: pre-wrap;
  line-height: 1.55;
  user-select: text; -webkit-user-select: text;
}

.spin {
  width: 16px; height: 16px; flex: none;
  border: 2px solid var(--line-2);
  border-top-color: var(--accent);
  border-radius: var(--r-full);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.section + .section { margin-top: var(--s-6); }
.section-head { display: flex; align-items: baseline; gap: var(--s-3); margin-bottom: var(--s-4); }
.section-head h2 { flex: 1; }
/* What a reader found, said in the head of the section it filled. */
.head-status { font-size: var(--t-sm); color: var(--ink-3); text-align: right; }
.head-status.is-ok { color: var(--ok); }
.head-status.is-err { color: var(--err); }
.status-warn { font-size: var(--t-sm); color: var(--ink-2); margin: 0 0 var(--s-3); padding-left: var(--s-3); border-left: 2px solid var(--accent); }
.importer.is-ok { border-color: var(--ok); border-style: solid; background: rgba(75,168,113,.08); }

/* ---------- lightbox: one photo, then the next ---------- */
.lightbox {
  position: fixed; inset: 0; z-index: 70; background: rgba(0,0,0,.92);
  display: grid; place-items: center; animation: fade var(--dur-2) var(--ease);
}
.lightbox[hidden] { display: none; }
body:has(.lightbox:not([hidden])) .nav { visibility: hidden; }
.lightbox img { max-width: 96vw; max-height: 88vh; object-fit: contain; border-radius: var(--r-md); user-select: none; -webkit-user-drag: none; }
.lightbox-x, .lightbox-nav {
  position: absolute; border: 0; border-radius: var(--r-full); color: #fff; cursor: pointer;
  background: rgba(255,255,255,.12); backdrop-filter: blur(8px); display: grid; place-items: center;
}
.lightbox-x { top: var(--s-4); right: var(--s-4); width: 40px; height: 40px; font-size: 22px; }
.lightbox-nav { top: 50%; transform: translateY(-50%); width: 44px; height: 64px; font-size: 34px; line-height: 1; }
.lightbox-nav.prev { left: var(--s-3); } .lightbox-nav.next { right: var(--s-3); }
.lightbox-nav:disabled { opacity: .25; cursor: default; }
.lightbox-cap { position: absolute; bottom: var(--s-4); left: 0; right: 0; display: flex; justify-content: center; align-items: center; gap: var(--s-3); flex-wrap: wrap; padding: 0 var(--s-4); color: rgba(255,255,255,.7); font-size: var(--t-sm); }

/* ---------- VIN scan ---------- */
.scan-video { width: 100%; aspect-ratio: 4 / 3; background: #000; border-radius: var(--r-md); object-fit: cover; }

/* ---------- scrollbars, in the theme ---------- */
* { scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--ink-3); background-clip: padding-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* Window sticker importer. Sits above the vehicle form because filling
   the form from a PDF is strictly better than typing it. */
.importer {
  padding: var(--s-4);
  margin-bottom: var(--s-5);
  border: 1px dashed var(--line-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

/* ---------- options ---------- */
.chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.chip {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 1px;
  min-height: var(--tap);
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--dur-1) var(--ease), background var(--dur-1) var(--ease),
              color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
}
.chip:active { transform: scale(.97); }
.chip[aria-pressed="true"] {
  border-color: var(--accent); background: var(--accent-wash); color: var(--accent);
}
.chip strong { font-size: var(--t-sm); font-weight: 650; }
.chip span { font-size: 10px; opacity: .8; }

.opts { display: flex; flex-direction: column; gap: var(--s-1); }
.opt {
  display: flex; align-items: center; gap: var(--s-4);
  min-height: 56px;
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--line);
}
.opt:last-child { border-bottom: 0; }
.opt-text { flex: 1; min-width: 0; }
.opt-text strong { display: block; font-size: var(--t-base); font-weight: 560; }
.opt-text span { font-size: var(--t-xs); color: var(--ink-3); }

/* A real switch rather than a checkbox: it is the standard control on
   both phone platforms, and a 44px target instead of a 13px one. */
.switch { position: relative; flex: none; width: 50px; height: 30px; }
.switch input {
  position: absolute; inset: 0; opacity: 0; margin: 0;
  width: 100%; height: 100%; cursor: pointer;
}
.switch i {
  position: absolute; inset: 0;
  border-radius: var(--r-full);
  background: var(--surface-3);
  transition: background var(--dur-2) var(--ease);
  pointer-events: none;
}
.switch i::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 24px; height: 24px; border-radius: var(--r-full);
  background: #fff; box-shadow: var(--sh-1);
  transition: transform var(--dur-2) var(--ease);
}
.switch input:checked + i { background: var(--accent); }
.switch input:checked + i::after { transform: translateX(20px); }
.switch input:focus-visible + i { outline: 2px solid var(--accent); outline-offset: 2px; }

.opt select.field, .opt input[type="range"] { max-width: 180px; flex: none; }

.chip.has-art { flex-direction: row; align-items: center; gap: var(--s-3); padding: var(--s-2); padding-right: var(--s-4); }
.chip-art { width: 64px; height: 64px; border-radius: var(--r-sm); flex: none; display: block; background: var(--line-2); }
.chip-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.chip:disabled { opacity: .45; cursor: not-allowed; }
.chip:disabled:active { transform: none; }

/* ---------- rendered clips ---------- */
.clipgrid { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.clip { margin: 0; }
/* A clip at its own shape, never taller than most of the screen: a
   vertical clip at full width was the whole phone. */
.clip video {
  display: block; width: auto; max-width: 100%; max-height: 62vh; margin: 0 auto; border-radius: var(--r-md);
  border: 1px solid var(--line); background: var(--sunken);
}
.clip figcaption { margin-top: var(--s-2); }

/* ---------- spec-driven controls ---------- */
/* Each group is a <details>: open when it changes something you can
   see on this host, shut when everything in it needs your own server.
   The summary carries what the group affects, so the preview beside it
   is never a mystery. */
.ctrl-group { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.ctrl-group + .ctrl-group { margin-top: var(--s-3); }
.ctrl-group > summary {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: var(--tap); padding: 0 var(--s-4);
  cursor: pointer; list-style: none; user-select: none;
}
.ctrl-group > summary::-webkit-details-marker { display: none; }
.ctrl-group > summary::after {
  content: ''; width: 8px; height: 8px; margin-left: auto;
  border-right: 1.5px solid var(--ink-3); border-bottom: 1.5px solid var(--ink-3);
  transform: rotate(-45deg); transition: transform var(--dur-1) var(--ease);
}
.ctrl-group[open] > summary::after { transform: rotate(45deg); }
.ctrl-group-head { font-size: var(--t-base); font-weight: 600; }
.ctrl-group-body { padding: 0 var(--s-4) var(--s-2); }
.ctrl-badge {
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  padding: 2px var(--s-2); border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-3);
}
.ctrl-badge.is-live { background: var(--accent-wash); color: var(--accent); }
.ctrl-badge.is-server { background: var(--sunken); }

/* ---------- the Studio: an editor, not a page ---------------------- */
/* The stage in the middle, a rail of tools and one open panel. The
   pane measures ITSELF (a container query), not the window: with the
   app's rail open, a 1100 px laptop window leaves the pane about 800
   px, which a viewport breakpoint treated as a phone. Nothing here
   scrolls but the panel, so the stage never leaves the screen. */
.pane.pane-studio { padding: 0; overflow: hidden; container-type: size; }
/* On a phone the rail is a second footer above the nav and the open
   tool's panel is a card that slides up over the lower half of the
   stage; the stage has the whole screen when no tool is open. */
.studio {
  --rail-h: 64px;
  height: 100%; display: grid; position: relative;
  grid-template-rows: minmax(0, 1fr) var(--rail-h);
  grid-template-areas: "stage" "rail";
}
.studio-stage {
  grid-area: stage; display: flex; flex-direction: column; align-items: center; gap: var(--s-2);
  padding: var(--s-3) var(--gutter) var(--s-2); min-height: 0;
}
/* The stage box is the room the frame has: a third of the screen on a
   phone, whatever the height leaves on a wide pane. The frame inside
   it takes the chosen format's own shape (preview.js fitStage), so a
   story stands tall and a landscape lies wide, each as large as fits. */
.stage-box { --stage-room: fill; width: 100%; height: auto; min-height: 0; display: grid; place-items: center; }
/* With the card open the stage keeps to the top of the screen, the
   frame and the shape chips above the card's edge. */
.studio-stage { justify-content: space-between; }
/* With the card open the stage is the room above the card's edge: the
   frame takes what that leaves after the bar, at any screen height. */
.studio.panel-open .studio-stage { height: 46%; }
/* On a phone the bar is one row: the segment and the shape chips by
   name alone; the pressed chip says what the stage shows, and the
   pixel sizes are in the Output tool. */
.preview-caption { display: none; }
.chip.fmt .fmt-text span { display: none; }
.chip.fmt { min-height: 32px; padding: var(--s-1) var(--s-2) var(--s-1) var(--s-2); }
.preview-frame {
  position: relative; border-radius: var(--r-lg); overflow: hidden;
  border: 1px solid var(--line); background: var(--sunken);
  box-shadow: var(--sh-2, 0 10px 30px rgba(0,0,0,.25));
  display: grid; place-items: center;
  width: 34vh; height: 34vh; max-width: 100%; max-height: 100%;
}
.preview-canvas { width: 100%; height: 100%; display: block; touch-action: none; }
.preview-canvas.has-text { cursor: grab; }
.preview-canvas.is-dragging { cursor: grabbing; }
.preview-canvas.is-busy { opacity: .8; }
.stage-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s-2) var(--s-3); width: 100%; }
/* Under the stage, not on it: a badge over the picture sat on top of
   the still's own text. */
.preview-caption { font-size: var(--t-xs); font-weight: 600; letter-spacing: .02em; color: var(--ink-3); }
/* Still | Video, one segment. */
.segment { display: inline-flex; padding: 2px; border-radius: var(--r-full); background: var(--surface-3); }
.seg {
  border: 0; background: transparent; color: var(--ink-3); cursor: pointer;
  min-height: 28px; padding: 0 var(--s-3); border-radius: var(--r-full);
  font-size: var(--t-xs); font-weight: 650;
}
.seg[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--sh-1); }
#previewScrub { width: 100%; max-width: 360px; accent-color: var(--accent); }
#previewScrub[hidden] { display: none; }
/* The shapes: tap the chip to see one, tick it to make it. */
.preview-formats { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); }
.chip.fmt { flex-direction: row; align-items: center; gap: var(--s-2); min-height: 36px; padding: var(--s-1) var(--s-3) var(--s-1) var(--s-2); }
.chip.fmt .fmt-text { display: flex; flex-direction: column; gap: 0; }
.fmt-check {
  flex: none; width: 18px; height: 18px; border-radius: var(--r-full);
  border: 1.5px solid var(--line-2); background: var(--surface); color: transparent;
  display: grid; place-items: center; font-size: 12px; line-height: 1;
}
.fmt-check::before { content: '\2713'; }
.chip.fmt.is-on .fmt-check { background: var(--accent); border-color: var(--accent); color: #fff; }
.chip.fmt.is-on:not([aria-pressed="true"]) { color: var(--ink-2); }
.chip.fmt:not(.is-on) strong { color: var(--ink-3); }
.estimates {
  display: grid; grid-template-columns: auto 1fr; gap: var(--s-2) var(--s-4);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
  font-size: var(--t-sm);
}
.estimate { display: contents; }
.estimate strong { font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.estimate span { color: var(--ink-3); }

/* The rail: one button per tool, an icon over a word. A row across the
   pane on a phone, a column down its edge on a wide one. */
.studio-rail {
  grid-area: rail; display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none;
  padding: var(--s-1) var(--s-2); border-top: 1px solid var(--line);
  background: var(--surface); z-index: 3;
}
.studio-rail::-webkit-scrollbar { display: none; }
.studio-rail.can-scroll:not(.is-end) { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent); }
.studio-rail.can-scroll:not(.is-start) { -webkit-mask-image: linear-gradient(to right, transparent, #000 44px, #000 calc(100% - 44px), transparent); mask-image: linear-gradient(to right, transparent, #000 44px, #000 calc(100% - 44px), transparent); }
.studio-rail.can-scroll.is-end:not(.is-start) { -webkit-mask-image: linear-gradient(to right, transparent, #000 44px); mask-image: linear-gradient(to right, transparent, #000 44px); }
.tool {
  flex: 1 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-width: 60px; min-height: 52px; padding: var(--s-1) var(--s-2);
  border: 0; border-radius: var(--r-md); background: transparent; color: var(--ink-3); cursor: pointer;
  font-size: 10px; font-weight: 600; letter-spacing: .03em; white-space: nowrap;
  transition: color var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
.tool svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.tool svg text { fill: currentColor; stroke: none; font-size: 13px; font-weight: 700; }
.tool:hover { color: var(--ink); background: var(--surface-2); }
.tool[aria-selected="true"] { color: var(--accent); background: var(--accent-wash); }
.tool.is-server { opacity: .55; }

/* The panel: the open tool's levers, and the only thing that scrolls. */
.studio-panel {
  position: absolute; left: 0; right: 0; bottom: var(--rail-h); top: 46%; z-index: 2;
  min-height: 0; display: flex; flex-direction: column;
  background: var(--surface); border-top: 1px solid var(--line);
  border-radius: var(--r-xl) var(--r-xl) 0 0; box-shadow: 0 -12px 40px rgba(0,0,0,.35);
  transform: translateY(calc(100% + 8px)); transition: transform var(--dur-2) var(--ease);
}
.studio.panel-open .studio-panel { transform: none; }
.panel-head {
  flex: none; display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--gutter) var(--s-2);
}
.panel-close { display: inline-grid; }
.panel-head h2 { flex: 1; font-size: var(--t-base); }
.panel-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 var(--gutter) var(--s-8); }
.ctrl-panel { padding: 0 0 var(--s-2); }
/* The looks as a grid of pictures: the tile is the choice. */
.looks-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--s-3); }
.looks-grid .chip.has-art { flex-direction: column; align-items: stretch; padding: 6px; gap: var(--s-2); }
.looks-grid .chip-art { width: 100%; height: auto; aspect-ratio: 1; }
.looks-grid .chip-text { padding: 0 var(--s-1) var(--s-1); align-items: center; text-align: center; }
.looks-grid .chip strong { font-size: var(--t-base); }

@container (min-width: 720px) {
  .studio {
    grid-template-columns: 72px minmax(0, 1fr) minmax(300px, 340px);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "rail stage panel";
  }
  .studio-rail { flex-direction: column; overflow-x: hidden; overflow-y: auto; padding: var(--s-3) var(--s-1); border: 0; border-right: 1px solid var(--line); }
  .tool { flex: none; min-width: 0; }
  /* The stage's bar is anchored at the bottom; the frame takes the room above it. */
  .studio-stage { justify-content: space-between; padding: var(--s-6); overflow: hidden; }
  /* The panel is a column of its own, always open; the card rules are undone. */
  .studio-panel { position: static; grid-area: panel; transform: none; border-radius: 0; box-shadow: none; border-top: 0; }
  .studio.panel-open .studio-stage { height: auto; }
  .panel-close { display: none; }
  .preview-caption { display: block; }
  .chip.fmt .fmt-text span { display: block; }
  .chip.fmt { min-height: 36px; padding: var(--s-1) var(--s-3) var(--s-1) var(--s-2); }
  /* As big as the height leaves, after the bar under it. */
  .stage-box { flex: none; }
  .studio-panel { border-left: 1px solid var(--line); background: var(--surface); }
  .panel-head, .panel-body { padding-left: var(--s-5); padding-right: var(--s-5); }
}

.opt.is-locked .opt-text strong { color: var(--ink-3); }
.opt.is-locked { opacity: .72; }
/* The group's closing line for what this host cannot do. */
.opt.opt-more { min-height: 0; padding-top: var(--s-3); }
.opt.opt-more .opt-text strong { font-size: var(--t-sm); color: var(--ink-3); }
.opt.opt-more .opt-text span { line-height: 1.5; }
/* A line of text stacks under its label: side by side, the box either
   squeezes the hint to a word a line or is too short to type in. */
.opt.opt-stack { flex-direction: column; align-items: stretch; gap: var(--s-2); }
.opt.opt-stack input.field { width: 100%; max-width: none; }

/* Swatches: the studio's own pickers. A tile is a picture of the choice
   (a gradient from the vehicle's paint, a stock photo, a frame, a
   colour), its name, and one line under it. */
.opt.opt-block { flex-direction: column; align-items: stretch; gap: var(--s-3); }
.swatches {
  display: grid; gap: var(--s-3);
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
}
.swatch {
  position: relative;
  display: flex; flex-direction: column; align-items: stretch; gap: 4px;
  padding: 6px; border: 1.5px solid var(--line-2); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink-2); text-align: left; cursor: pointer;
  transition: border-color var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
.swatch:hover:not(:disabled) { border-color: var(--ink-3); }
.swatch[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-wash); color: var(--ink); }
.swatch:disabled, .swatch.is-locked { opacity: .5; cursor: not-allowed; }
.swatch-thumb {
  display: block; aspect-ratio: 1; border-radius: var(--r-sm); overflow: hidden;
  background: var(--sunken); border: 1px solid var(--line);
  background-image: linear-gradient(45deg, var(--surface-3) 25%, transparent 25%, transparent 75%, var(--surface-3) 75%),
                    linear-gradient(45deg, var(--surface-3) 25%, transparent 25%, transparent 75%, var(--surface-3) 75%);
  background-size: 12px 12px; background-position: 0 0, 6px 6px;
}
.swatch-thumb canvas, .swatch-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.swatch-thumb.is-plain { background: var(--sunken); }
.swatch-thumb[data-control="border"] { background-image: none; background: #2a2d33; }
.swatch-thumb.is-upload { display: grid; place-items: center; background: var(--sunken); }
.swatch-thumb.is-upload::before {
  content: '+'; font-size: 28px; font-weight: 300; color: var(--ink-3); line-height: 1;
}
/* Two lines of name at most, and always the room for two, so a row of
   tiles keeps one baseline whether a name is "Studio" or "Futuristic
   Showroom". */
.swatch-label {
  font-size: var(--t-sm); font-weight: 600; line-height: 1.2; min-height: 2.4em; text-align: center;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.opt.opt-block { padding-top: var(--s-3); }
.opt.opt-block .opt-text span:only-child { font-size: var(--t-sm); color: var(--ink-2); }
.swatch-hint { font-size: 10px; color: var(--ink-3); line-height: 1.25; text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A configurator's style row and its colour dots. */
/* A configurator's style row: a strip of pills that wraps as pills,
   never as words inside one pill. */
.seg-wrap { display: flex; flex-wrap: wrap; gap: 6px; padding: 0; background: transparent; border-radius: 0; }
.seg-wrap .seg { background: var(--surface-3); min-height: 32px; padding: 0 var(--s-4); }
.seg-wrap .seg[aria-pressed="true"] { background: var(--ink); color: var(--bg); box-shadow: none; }
.seg-wrap .seg:hover:not([aria-pressed="true"]) { color: var(--ink); }
/* A lever row keeps its words: the widget takes what it needs and the
   label wraps rather than clips; a slider with an Auto button stacks
   under its label in a narrow panel. */
.panel-body { container-type: inline-size; container-name: panel; }
.opt .range-wrap { flex: 0 1 auto; min-width: 0; }
.opt .range-wrap input[type="range"] { flex: 1 1 90px; min-width: 70px; width: auto; }
@container panel (max-width: 440px) {
  .opt:has(.range-wrap) { flex-direction: column; align-items: stretch; gap: var(--s-2); }
  .opt:has(.range-wrap) .range-wrap { width: 100%; }
  .opt:has(.range-wrap) .range-wrap input[type="range"] { flex: 1 1 auto; max-width: none; }
}
.dots { display: flex; align-items: center; gap: var(--s-2); flex: none; }
.dot {
  width: 30px; height: 30px; border-radius: var(--r-full); border: 2px solid var(--line-2); padding: 0;
  background: var(--surface); cursor: pointer; position: relative; display: grid; place-items: center;
}
.dot[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-wash); }
.dot.is-plain { background: var(--surface-3); }
.dot-custom input {
  appearance: none; -webkit-appearance: none; width: 100%; height: 100%; padding: 0; border: 0;
  border-radius: var(--r-full); background: transparent; cursor: pointer;
}
.dot-custom input::-webkit-color-swatch-wrapper { padding: 0; }
.dot-custom input::-webkit-color-swatch { border: 0; border-radius: var(--r-full); }
.dot-custom input::-moz-color-swatch { border: 0; border-radius: var(--r-full); }
.dot-custom.is-auto { background: conic-gradient(#f66, #fc6, #6f6, #6ff, #66f, #f6f, #f66); }
.dot-custom.is-auto input::-webkit-color-swatch { opacity: 0; }
.dot-same { background: var(--surface-3); color: var(--ink-3); font: 600 12px/1 var(--font); }
.place-wrap { display: flex; align-items: center; gap: var(--s-2); flex: none; }
.place-same[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); background: var(--accent-wash); }
.range-wrap.is-auto input[type="range"] { opacity: .45; }
/* The text's place: a 3x2 grid, the chosen cell filled. */
.place { display: grid; grid-template-columns: repeat(3, 26px); grid-template-rows: repeat(2, 26px); gap: 3px; flex: none; }
@media (pointer: coarse) {
  .place { grid-template-columns: repeat(3, 36px); grid-template-rows: repeat(2, 36px); gap: 4px; }
  .place-cell i { width: 14px; height: 8px; }
  .fmt-check { width: 24px; height: 24px; }
  .grid.is-strip .tile-x { width: 28px; height: 28px; font-size: 14px; }
}
.place-cell { border: 1.5px solid var(--line-2); border-radius: 6px; background: var(--surface); padding: 0; cursor: pointer; display: grid; place-items: center; }
.place-cell i { width: 10px; height: 6px; border-radius: 2px; background: var(--line-2); display: block; }
.place-cell[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-wash); }
.place-cell[aria-pressed="true"] i { background: var(--accent); }
.opt .seg-wrap { flex: none; }
/* A heading across the grid for a category of library tiles. */
.swatch-group { grid-column: 1 / -1; font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); margin-top: var(--s-2); }
/* A tabbed group's tabs, above its controls. */
.ctrl-subtabs { margin: 0 0 var(--s-4); }
/* A choice's own colour, picked on its tile: a dot in the thumb's
   corner, shown while the tile is chosen. */
.swatch-dot {
  position: absolute; right: 12px; top: 12px; display: none; align-items: center; gap: 4px;
}
.swatch[aria-pressed="true"] .swatch-dot { display: flex; }
.swatch-dot input {
  appearance: none; -webkit-appearance: none; width: 28px; height: 28px; padding: 0;
  border: 2px solid #fff; border-radius: var(--r-full); background: transparent; cursor: pointer;
  box-shadow: 0 2px 8px rgba(0,0,0,.45);
}
.swatch-dot input::-webkit-color-swatch-wrapper { padding: 0; }
.swatch-dot input::-webkit-color-swatch { border: 0; border-radius: var(--r-full); }
.swatch-dot input::-moz-color-swatch { border: 0; border-radius: var(--r-full); }
.swatch-dot.is-auto input { background: conic-gradient(#f66, #fc6, #6f6, #6ff, #66f, #f6f, #f66); }
.swatch-dot.is-auto input::-webkit-color-swatch { opacity: 0; }
.swatch-dot-x {
  width: 20px; height: 20px; display: grid; place-items: center; border-radius: var(--r-full);
  background: rgba(0,0,0,.6); color: #fff; font-size: 12px; line-height: 1; cursor: pointer;
}
/* The Your-own tile: the platform picker fills the thumb. */
.swatch-custom .swatch-thumb { padding: 0; }
.swatch-color {
  appearance: none; -webkit-appearance: none; width: 100%; height: 100%; padding: 0; border: 0;
  background: transparent; cursor: pointer; display: block;
}
.swatch-color::-webkit-color-swatch-wrapper { padding: 0; }
.swatch-color::-webkit-color-swatch { border: 0; }
.swatch-color::-moz-color-swatch { border: 0; }
.swatch-custom .swatch-thumb.is-plain .swatch-color { opacity: 0; }
.swatch-custom .swatch-thumb.is-plain::before {
  content: ''; position: absolute; inset: 0;
  background: conic-gradient(#f66, #fc6, #6f6, #6ff, #66f, #f6f, #f66);
  mask: radial-gradient(circle at center, transparent 35%, #000 36%);
  -webkit-mask: radial-gradient(circle at center, transparent 35%, #000 36%);
  opacity: .8;
}
.swatch-custom .swatch-thumb { position: relative; }
/* An upload's remove button, in its corner. */
.swatch-x {
  position: absolute; top: 10px; right: 10px; width: 22px; height: 22px;
  display: grid; place-items: center; border-radius: var(--r-full);
  background: rgba(0,0,0,.6); color: #fff; font-size: 13px; line-height: 1; cursor: pointer;
}

.file-wrap { display: flex; align-items: center; gap: var(--s-2); flex: none; }
/* The colour picker: a round swatch (the platform's picker behind it),
   the hex beside it, and the way back to the paint. */
.color-wrap { display: flex; align-items: center; gap: var(--s-2); flex: none; }
.color-input {
  appearance: none; -webkit-appearance: none; width: 36px; height: 36px; padding: 0;
  border: 1.5px solid var(--line-2); border-radius: var(--r-full); background: transparent; cursor: pointer;
}
.color-input::-webkit-color-swatch-wrapper { padding: 3px; }
.color-input::-webkit-color-swatch { border: 0; border-radius: var(--r-full); }
.color-input::-moz-color-swatch { border: 0; border-radius: var(--r-full); }
.color-wrap.is-auto .color-input { background: repeating-conic-gradient(var(--surface-3) 0 25%, var(--surface) 0 50%) 0 0 / 12px 12px; }
.color-wrap.is-auto .color-input::-webkit-color-swatch { opacity: 0; }
.color-word { font-size: var(--t-xs); font-family: var(--mono, ui-monospace, monospace); color: var(--ink-3); min-width: 5.5ch; }
.file-thumb { width: auto; height: 40px; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--sunken); }

.range-wrap { display: flex; align-items: center; gap: var(--s-3); flex: none; }
.range-wrap input[type="range"] { width: 130px; accent-color: var(--accent); }
.range-out {
  min-width: 46px; text-align: right;
  font-size: var(--t-sm); font-variant-numeric: tabular-nums; color: var(--ink-2);
}

/* ---------- library ------------------------------------------------ */
.lib-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.lib-more { display: block; margin: var(--s-4) auto 0; }
@media (min-width: 640px) { .lib-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); } }
.lib-card { cursor: pointer; }
.lib-card:hover .tile { border-color: var(--accent); }
.lib-card-body { display: flex; flex-direction: column; gap: 2px; padding: var(--s-2) 2px 0; }
.lib-title {
  font-size: var(--t-sm); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.lib-nohero { display: grid; place-items: center; height: 100%; color: var(--ink-3); font-size: var(--t-sm); }
.lib-media-row { display: flex; gap: var(--s-3); overflow-x: auto; padding-bottom: var(--s-2); scroll-snap-type: x proximity; }
.lib-media {
  flex: none; width: 220px; display: flex; flex-direction: column; gap: 4px;
  scroll-snap-align: start; color: inherit; text-decoration: none;
}
.lib-media img, .lib-media video {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--r-md); background: var(--sunken); border: 1px solid var(--line);
}
.lib-media video { aspect-ratio: auto; max-height: 300px; }
.lib-status {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4);
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
}
.lib-danger { color: var(--err); }
.lib-danger:hover:not(:disabled) { border-color: var(--err); }
.lib-history { display: flex; flex-direction: column; gap: var(--s-2); }
.lib-run {
  display: grid; grid-template-columns: 150px auto 1fr; gap: var(--s-3); align-items: center;
  padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
}
.lib-run.is-failed { border-color: var(--err); }
.lib-run-what a { color: var(--accent); text-decoration: none; }
@media (max-width: 559px) { .lib-run { grid-template-columns: 1fr auto; } .lib-run-what { grid-column: 1 / -1; } }
