/* dmx.css: Krank'd DMX tools. Layers on app.css (shared design tokens).
   Patch Studio (dmx.html) + standalone dip-switch calculator (dipswitch.html). */

/* ===================== base utils ===================== */
.cross-link { text-decoration: none; }
.hr { border: 0; border-top: 1px solid var(--line); margin: 18px 0; }
.mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-variant-ligatures: none; letter-spacing: .03em; }
.hidden { display: none !important; }
.ic { display: inline-flex; align-items: center; justify-content: center; }
.ic svg { display: block; }

:where(button, a, input, select, [tabindex]):focus-visible {
  outline: 2px solid var(--purple-l); outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }

/* ===================== Krank'd branding ===================== */
.brand { display: flex; align-items: center; gap: 13px; text-decoration: none; color: inherit; }
.brand:hover { text-decoration: none; }
/* the monogram art is dark: invert to white for the dark UI + purple glow */
.brand-logo { width: 48px; height: 48px; flex: none; object-fit: contain;
  filter: invert(1) drop-shadow(0 3px 14px rgba(125, 40, 219, .6)); }
.brand .title { line-height: 1.12; }
.brand .title b { font-family: 'Poppins', sans-serif; font-weight: 800; font-size: 19px; letter-spacing: -.015em; display: block; }
.brand .title small { color: var(--tx-dim); font-size: 12px; }

.kd-ambient {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(1000px 520px at 50% -10%, rgba(125, 40, 219, .24), transparent 62%);
}
.shell { position: relative; z-index: 1; }

/* buttons (extend app.css .btn with icon support) */
.btn { display: inline-flex; align-items: center; gap: 7px; transition: background .15s, border-color .15s, transform .08s, color .15s; }
.btn:active { transform: translateY(1px); }
.btn.ghost { background: transparent; border-color: var(--line); color: var(--tx-dim); }
.btn.ghost:hover { color: var(--bad); border-color: var(--bad); background: var(--bad-bg); }
.card-head { display: flex; align-items: center; gap: 9px; margin-bottom: 16px; }
.card-head .ic { color: var(--purple-xl); }
.card-head h2, .card-head h3 { margin: 0; font-size: 13px; text-transform: uppercase; letter-spacing: .08em; color: var(--tx-dim); font-weight: 700; }
.lbl { display: block; font-size: 12px; font-weight: 600; color: var(--tx-dim); margin-bottom: 8px; letter-spacing: .02em; }
.hint { margin: 8px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--tx-faint); }
.hint .ic { color: var(--purple-xl); vertical-align: -1px; }

/* =====================================================================
   DECODER (standalone dipswitch.html): kept intact
   ===================================================================== */
.dmx-grid { display: grid; gap: 18px; grid-template-columns: minmax(0, 340px) minmax(0, 1fr); align-items: start; }
.dmx-grid > * { min-width: 0; }
/* minmax(0,1fr), never bare 1fr: 1fr = minmax(auto,1fr), and the 450px+ dip-switch bank's
   min-content would force the column (and the page) wider than a phone viewport */
@media (max-width: 1020px) { .dmx-grid { grid-template-columns: minmax(0, 1fr); } }

details.adv { margin: 16px 0 0; border-top: 1px solid var(--line); padding-top: 12px; }
details.adv > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; color: var(--tx-dim); font-size: 12.5px; font-weight: 600; user-select: none; }
details.adv > summary::-webkit-details-marker { display: none; }
details.adv > summary::before { content: '▸'; color: var(--purple-l); transition: transform .15s; font-size: 11px; }
details.adv[open] > summary::before { transform: rotate(90deg); }
details.adv > summary:hover { color: var(--tx); }
details.adv .adv-label { color: var(--tx); }

.addr-row { gap: 8px; }
.addr-box { font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 26px; text-align: center; padding: 8px 10px; letter-spacing: .02em; }
.addr-box::-webkit-outer-spin-button, .addr-box::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.btn.step { font-size: 20px; line-height: 1; width: 46px; padding: 6px 0; flex: none; font-weight: 700; justify-content: center; }
.hero-card .result-hero .num { font-size: 64px; }

.bank-card { padding: 18px; }
/* margin:auto centres the bank when there is room; overflow-x scrolls it inside the card
   (never the page) when there is not, e.g. a 10-switch bank on a phone */
.bank-stage { display: flex; overflow-x: auto; padding: 22px 10px 10px; border-radius: 14px;
  background: radial-gradient(120% 90% at 50% -10%, rgba(155,77,255,.10), transparent 60%), linear-gradient(180deg, #0e1120, #0a0c16); border: 1px solid var(--line); }
.bank-stage .dipbank { margin: 0 auto; }
.bank-hint { text-align: center; margin: 12px 0 0; }
.dipbank { display: inline-flex; gap: 6px; padding: 14px 14px 10px; border-radius: 12px;
  background: linear-gradient(180deg, #2b3666 0%, #202a52 40%, #1a2244 100%); border: 1px solid #3a478a;
  box-shadow: inset 0 2px 0 rgba(255,255,255,.10), inset 0 -3px 8px rgba(0,0,0,.5), 0 10px 28px -10px rgba(0,0,0,.8); }
.dipsw { appearance: none; border: 0; background: transparent; cursor: default; padding: 0; display: flex; flex-direction: column; align-items: center; gap: 5px; width: 42px; color: var(--tx); }
.dipbank button.dipsw { cursor: pointer; }
button.dipsw:focus-visible { outline: none; box-shadow: none; }
button.dipsw:focus-visible .dip-track { box-shadow: 0 0 0 2px var(--purple-l), inset 0 2px 6px rgba(0,0,0,.7); }
.dip-on { font-size: 9px; font-weight: 700; letter-spacing: .12em; color: #6f7aa8; transition: color .18s; }
.dip-track { position: relative; width: 26px; height: 82px; border-radius: 6px; background: linear-gradient(180deg, #07090f, #0c1020); box-shadow: inset 0 2px 7px rgba(0,0,0,.8), inset 0 0 0 1px rgba(255,255,255,.03); overflow: hidden; }
.dip-rocker { position: absolute; left: 3px; right: 3px; top: 3px; height: 40px; border-radius: 4px;
  background: linear-gradient(180deg, #fdfbf4 0%, #ece6d4 55%, #cfc8b4 100%);
  box-shadow: 0 2px 4px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.9), inset 0 -2px 3px rgba(0,0,0,.18);
  transform: translateY(36px); transition: transform .18s cubic-bezier(.34,1.4,.5,1), background .18s; }
.dip-rocker::after { content: ''; position: absolute; left: 5px; right: 5px; top: 50%; height: 9px; transform: translateY(-50%); border-radius: 2px; background: repeating-linear-gradient(180deg, rgba(0,0,0,.16) 0 1.5px, transparent 1.5px 3px); }
.dipsw.on .dip-rocker { transform: translateY(0); background: linear-gradient(180deg, #ffffff 0%, #f3eefd 55%, #d9ccff 100%); }
.dipsw.on .dip-track { box-shadow: inset 0 2px 7px rgba(0,0,0,.8), inset 0 0 14px rgba(155,77,255,.55), inset 0 0 0 1px rgba(155,77,255,.5); }
.dipsw.on .dip-on { color: var(--purple-xl); }
.dipsw.hl .dip-track { animation: dip-pop .5s ease; }
@keyframes dip-pop { 0%,100% { } 30% { box-shadow: inset 0 2px 7px rgba(0,0,0,.8), inset 0 0 20px rgba(155,77,255,.9), inset 0 0 0 1px rgba(155,77,255,.8); } }
button.dipsw:hover .dip-track { box-shadow: inset 0 2px 7px rgba(0,0,0,.8), inset 0 0 0 1px rgba(155,77,255,.35); }
.dip-num { font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 14px; line-height: 1; }
.dip-wt { font-size: 10px; color: var(--tx-faint); font-variant-numeric: tabular-nums; }
.sumline { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; font-family: 'Poppins', sans-serif; }
.sum-eq { font-weight: 800; font-size: 30px; color: #fff; }
.sum-eq::after { content: '='; margin-left: 9px; color: var(--tx-faint); font-weight: 600; }
.sum-op { color: var(--tx-faint); font-weight: 700; font-size: 18px; }
.sum-chip { display: inline-flex; padding: 5px 12px; border-radius: 9px; font-weight: 700; font-size: 16px; background: #1a1430; color: var(--purple-xl); border: 1px solid #3a2a66; font-variant-numeric: tabular-nums; }
.copied-note { margin-left: 4px; }

/* =====================================================================
   PATCH STUDIO (dmx.html)
   ===================================================================== */
.studio-grid { display: grid; gap: 20px; grid-template-columns: minmax(280px, 350px) minmax(0, 1fr); align-items: start; }
.studio-side { display: flex; flex-direction: column; gap: 18px; position: sticky; top: 18px; min-width: 0; }
.studio-main { min-width: 0; }
/* 1080, not 980: the 9-column sheet's floor is ~690px, which a two-column layout can't
   honor below ~1080. Single column gives the patch sheet: the artefact: full width. */
@media (max-width: 1080px) { .studio-grid { grid-template-columns: minmax(0, 1fr); } .studio-side { position: static; } }

/* The sticky rail is taller than most windows once Add and Settings are both open, so the
   bottom of Settings could only be reached by scrolling the whole page to its end. Cap it to
   the window and give it its own scroll instead. The side and bottom padding is room for the
   cards' shadows and focus rings, which the scroll box would otherwise clip; the matching
   negative margins put the cards back on the grid line they sat on, and park the scrollbar in
   the 20px column gap. Not below the 1080 collapse, where the rail is a normal block again. */
@media screen and (min-width: 1081px) {
  .studio-side {
    max-height: calc(100vh - 36px);
    overflow-y: auto;
    /* deliberately NOT overscroll-behavior: contain. The rail is only stuck once the page has
       scrolled past the meta card; before that its capped box runs below the fold, and containing
       the scroll traps the wheel in a box whose bottom nobody can see. Chaining hands the wheel to
       the page at the rail's bottom, the rail sticks, and the last of Settings comes into view in
       one gesture. Verified by wheel events from scrollY 0 at 1440x800. */
    overflow-x: hidden;
    padding: 4px 12px 18px 6px;
    margin: -4px -20px -18px -6px;
    scrollbar-color: #3a2a66 transparent;
  }
  .studio-side::-webkit-scrollbar { width: 8px; }
  .studio-side::-webkit-scrollbar-thumb { background: #3a2a66; border-radius: 999px; }
  .studio-side::-webkit-scrollbar-thumb:hover { background: var(--purple); }
}

/* Wide screens: the 1240px shell left the sheet at its 1280px width on a 27" monitor. */
@media screen and (min-width: 1500px) {
  body.dmx-body .shell { max-width: 1800px; }
  body.dmx-body .studio-grid { grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); }
}

/* patch header (show / venue / date / LD) */
.meta-card { display: grid; grid-template-columns: 1.5fr 1.5fr .9fr 1.1fr; gap: 16px; padding: 16px 18px; margin-bottom: 18px; }
@media (max-width: 760px) { .meta-card { grid-template-columns: 1fr 1fr; } }
@media (max-width: 460px) { .meta-card { grid-template-columns: 1fr; } }
.meta-field { display: flex; flex-direction: column; gap: 6px; }
.meta-field > span { font-size: 11px; font-weight: 600; color: var(--tx-faint); text-transform: uppercase; letter-spacing: .06em; }

/* ---- add card ---- */
.add-card .field { margin-bottom: 18px; }
.add-card .field:last-child { margin-bottom: 0; }
.pos-input { font-weight: 600; }
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.chip { appearance: none; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 600;
  padding: 5px 12px; border-radius: 999px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx-dim);
  transition: background .14s, border-color .14s, color .14s; }
.chip:hover { color: var(--tx); border-color: var(--purple-l); }
.chip.active { background: rgba(125, 40, 219, .22); border-color: var(--purple-l); color: var(--purple-xl); }

/* searchable fixture combobox */
.combo { position: relative; }
.combo-ic { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--tx-faint); pointer-events: none; display: inline-flex; }
/* element+class selector beats app.css `input[type='text']` so the search icon never overlaps the text */
.combo input.combo-input { width: 100%; padding-left: 38px; }
.combo-panel { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30; max-height: 320px; overflow-y: auto;
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 12px; box-shadow: var(--shadow); padding: 6px; }
.combo-group { font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--tx-faint); padding: 9px 10px 4px; font-weight: 700; }
.combo-opt { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 8px 10px; border-radius: 8px; cursor: pointer; }
.combo-opt:hover { background: var(--el-2); }
.combo-opt .co-name { font-weight: 600; font-size: 13.5px; }
.combo-opt.custom { border-top: 1px solid var(--line); margin-top: 4px; }
.combo-opt.custom .co-name { color: var(--purple-xl); }
.ch-in { width: 90px; text-align: center; }
.chan-add-in { width: 110px; text-align: left; }
/* duplicate fixture IDs get an amber outline on the sheet (screen-only editing aid) */
.chan-edit.dup { outline: 2px solid var(--warn, #ffb454); outline-offset: -2px; border-radius: 6px; }
.custom-wrap { margin-top: 10px; }

/* mode pills */
.mode-row { display: flex; flex-wrap: wrap; gap: 8px; }
.mode-pill { appearance: none; cursor: pointer; font: inherit; text-align: left; display: flex; flex-direction: column; gap: 1px;
  padding: 7px 12px; border-radius: 10px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx); transition: all .14s; }
.mode-pill:hover { border-color: var(--purple-l); }
.mode-pill.active { border-color: var(--purple-l); background: linear-gradient(180deg, #241640, var(--el)); box-shadow: inset 0 0 0 1px rgba(155,77,255,.4); }
.mode-pill b { font-weight: 600; font-size: 13px; }
/* long mode lists (an Astera tube publishes 165): grouped select under the one active pill */
.mode-picker-wrap { display: flex; align-items: center; gap: 10px; width: 100%; }
.mode-picker { flex: 1; min-width: 0; appearance: none; -webkit-appearance: none; font: inherit; font-size: 13.5px; color: var(--tx); cursor: pointer;
  background: var(--el) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23b48cff' stroke-width='1.8' stroke-linecap='round'/></svg>") no-repeat right 12px center;
  border: 1px solid var(--line-2); border-radius: 10px; padding: 10px 34px 10px 12px; }
.mode-picker:hover { border-color: var(--purple-l); }
.mode-picker:focus { outline: none; border-color: var(--purple-l); box-shadow: 0 0 0 3px rgba(155,77,255,.25); }
.mode-picker optgroup { color: var(--purple-xl); font-style: normal; font-weight: 700; }
.mode-picker option { color: var(--tx); font-weight: 400; }
/* undo / redo live in the sheet card head, right-aligned like the universe filter tag */
.hist-btns { margin-left: auto; display: flex; gap: 6px; }
.hist-btn[disabled] { opacity: .38; cursor: default; }
.mode-pill small { color: var(--tx-dim); font-size: 11px; }

/* qty stepper + add */
.qty-add { display: flex; align-items: center; gap: 12px; }
.stepper { display: inline-flex; align-items: center; background: var(--bg); border: 1px solid var(--line-2); border-radius: 11px; padding: 3px; flex: none; }
.step-btn { appearance: none; cursor: pointer; border: 0; background: transparent; color: var(--tx-dim); width: 34px; height: 34px; flex: none; padding: 0; display: grid; place-items: center; border-radius: 8px; transition: all .14s; }
.step-btn:hover { color: #fff; background: var(--el-2); }
/* input.qty-in, not .qty-in: app.css `input[type='text']` is (0,1,1) and would stretch the count to
   100% width, squashing the Add button beside it (the 006b5ea regression) */
input.qty-in { min-width: 34px; width: 52px; text-align: center; font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 17px; font-variant-numeric: tabular-nums; background: none; border: 0; color: inherit; padding: 0; }
input.qty-in:focus-visible { outline: 2px solid var(--purple-l, #9b4dff); outline-offset: 2px; border-radius: 6px; }
.add-btn { flex: 1; justify-content: center; font-size: 14.5px; padding: 11px 16px; }

/* settings */
.settings-card .field { margin-bottom: 16px; }
.settings-card .field:last-child { margin-bottom: 0; }

/* ---- Standard vs Advanced mode ---- */
.adv-hint { display: none; }
body.advanced .adv-hint { display: block; }
body.advanced .std-only { display: none; }     /* reflow ignores the auto-fill flow control */
body.advanced .pin-ctl { display: none !important; }  /* locks replace per-bar universe pins */

/* lock buttons (universe + fixture) */
.lock-btn { appearance: none; cursor: pointer; font: inherit; font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; border-radius: 999px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx-dim); transition: all .14s; }
.lock-btn:hover { color: var(--tx); border-color: var(--purple-l); }
.lock-btn.on { background: linear-gradient(145deg, var(--purple-l), var(--purple)); border-color: transparent; color: #fff; }
.fx-lock.on { color: var(--purple-xl); }
.fx-lock.on:hover { color: #fff; background: var(--purple); border-color: var(--purple); }

/* locked styling */
.universe-row.locked .universe-track { outline: 2px solid var(--purple-l); outline-offset: 1px; }
.fx-row.locked td { background: linear-gradient(90deg, rgba(155,77,255,.08), transparent) !important; }
.fx-row.locked .addr-num { background: linear-gradient(160deg, #fff, var(--purple-l)); -webkit-background-clip: text; background-clip: text; }
.fx-row.unplaced td { background: rgba(252,165,165,.08) !important; }
.fx-row.unplaced .addr-num { -webkit-text-fill-color: var(--bad); }

/* tour-mode hint above the sheet */
.sheet-adv-hint { display: flex; align-items: center; gap: 9px; margin: 10px 0 2px; padding: 10px 13px; flex-wrap: wrap;
  background: linear-gradient(90deg, rgba(155,77,255,.12), transparent); border: 1px solid var(--line-2); border-left: 3px solid var(--purple-l);
  border-radius: 10px; font-size: 12.5px; line-height: 1.5; color: var(--tx-dim); }
.sheet-adv-hint > .ic { color: var(--purple-xl); flex: none; }
.sheet-adv-hint > span { flex: 1; min-width: 200px; }
.sheet-adv-hint span.ic { color: var(--purple-xl); vertical-align: -1px; }
.sheet-adv-hint b { color: var(--tx); font-weight: 700; }
.sheet-adv-hint .btn { flex: none; }

/* Standard-mode discoverability: advertise Tour-mode locking right in the sheet */
.sheet-std-cta { display: flex; align-items: center; gap: 11px; margin: 10px 0 2px; padding: 11px 14px;
  background: linear-gradient(90deg, rgba(155,77,255,.14), rgba(155,77,255,.04)); border: 1px solid var(--line-2); border-radius: 11px; font-size: 12.5px; line-height: 1.45; color: var(--tx-dim); flex-wrap: wrap; }
.sheet-std-cta > .ic { color: var(--purple-xl); flex: none; }
.sheet-std-cta b { color: var(--tx); font-weight: 700; }
.sheet-std-cta > span { flex: 1; min-width: 160px; }
.sheet-std-cta .btn { flex: none; }

/* Advanced/tour row: typed universe (a "U" chip you type a number into) + editable address
   with a prominent lock (element+class selectors: app.css input rules must not win) */
.uni-edit-wrap { display: inline-flex; align-items: center; gap: 1px; padding: 3px 3px 3px 8px; background: #1a1430; border: 1px solid #3a2a66;
  border-radius: 7px; color: var(--purple-xl); font-family: 'Poppins', sans-serif; transition: border-color .14s; }
.uni-edit-wrap > b { font-size: 11.5px; font-weight: 700; }
.uni-edit-wrap:hover, .uni-edit-wrap:focus-within { border-color: var(--purple-l); }
input.uni-edit { width: 30px; padding: 0 2px; font-size: 12.5px; font-weight: 700; text-align: left; color: var(--purple-xl);
  background: transparent; border: 0; border-radius: 0; font-family: 'Poppins', sans-serif; font-variant-numeric: tabular-nums; }
input.uni-edit:focus-visible { outline: none; box-shadow: none; }
input.uni-edit::-webkit-outer-spin-button, input.uni-edit::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.addr-static { display: inline-flex; align-items: baseline; gap: 6px; }
/* input + lock are an atomic .addr-main group the table can never split; the state pill
   (clash / no fit) wraps onto its own line under it rather than bleeding sideways */
.addr-edit-wrap { display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap; row-gap: 4px; max-width: 112px; justify-content: flex-end; }
.addr-edit-wrap > * { flex: none; }
.addr-main { display: inline-flex; align-items: center; gap: 7px; flex: none; }
input.addr-edit { width: 56px; padding: 6px 6px; font-family: 'Poppins', sans-serif; font-weight: 800; font-size: 17px; text-align: center;
  color: var(--purple-xl); background: var(--bg); border: 1px solid var(--line-2); border-radius: 8px; font-variant-numeric: tabular-nums; transition: border-color .14s; }
input.addr-edit::-webkit-outer-spin-button, input.addr-edit::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input.addr-edit:hover, input.addr-edit:focus { border-color: var(--purple-l); }
.addr-lock { appearance: none; cursor: pointer; flex: none; width: 33px; height: 33px; display: grid; place-items: center;
  border-radius: 8px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx-faint); transition: all .14s; }
.addr-lock:hover { color: #fff; border-color: var(--purple-l); }
.addr-lock.on { background: linear-gradient(145deg, var(--purple-l), var(--purple)); border-color: transparent; color: #fff; box-shadow: 0 3px 10px -4px rgba(125,40,219,.9); }
.fx-row.locked .addr-edit { border-color: var(--purple-l); background: linear-gradient(160deg, #241640, var(--bg)); }
.pos-lock { flex: none; }

/* ---- summary card ---- */
.summary-card { padding: 20px 22px; }
.stats { display: flex; gap: 30px; flex-wrap: wrap; }
.stats .stat { display: flex; flex-direction: column; line-height: 1.05; }
.stats .stat b { font-family: 'Poppins', sans-serif; font-weight: 800; font-size: 34px;
  background: linear-gradient(160deg, #fff, var(--purple-xl)); -webkit-background-clip: text; background-clip: text; color: transparent; font-variant-numeric: tabular-nums; }
.stats .stat span { font-size: 12px; color: var(--tx-dim); margin-top: 2px; text-transform: uppercase; letter-spacing: .05em; }

/* universe selector tabs */
.uni-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 4px; }
.uni-tab { appearance: none; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 600; display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: 999px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx-dim);
  transition: background .14s, border-color .14s, color .14s; }
.uni-tab:hover { color: var(--tx); border-color: var(--purple-l); }
.uni-tab.active { background: rgba(125, 40, 219, .22); border-color: var(--purple-l); color: var(--purple-xl); }
.uni-tab .ic { opacity: .85; }
.uni-tab .dot-u { width: 8px; height: 8px; border-radius: 50%; }
.uni-tab-pct { font-variant-numeric: tabular-nums; opacity: .85; font-size: 11px; } /* .7 measured 3.64:1 at 11px; 4.5 needed */
.uni-tab.active .uni-tab-pct { opacity: 1; }

/* per-universe fill bars */
.universe-row { margin-top: 16px; }
.uni-row-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; font-size: 13px; }
.uni-row-head b { font-family: 'Poppins', sans-serif; font-weight: 700; }
.universe-track { position: relative; height: 32px; border-radius: 9px; overflow: hidden; border: 1px solid var(--line-2);
  background: repeating-linear-gradient(90deg, rgba(255,255,255,.045) 0 1px, transparent 1px calc(100%/32)), var(--bg); }
.universe-bar { position: absolute; inset: 0; }
.uni-seg { position: absolute; top: 0; bottom: 0; border-right: 1px solid rgba(0,0,0,.35); box-shadow: inset 0 1px 0 rgba(255,255,255,.25); transition: width .2s ease; }

/* ---- sheet card ---- */
/* overflow-x: a 9-column sheet on a narrow window scrolls inside its card, never the page */
.sheet-card { padding: 20px 22px; overflow-x: auto; }
/* 1081-1170 window band: two columns only fit if the side rail is pinned to its minimum.
   min-width bound so the 1080px single-column collapse below still wins */
@media (min-width: 1081px) and (max-width: 1170px) {
  .studio-grid { grid-template-columns: 280px minmax(0, 1fr); }
}
.sheet-card .card-head { margin-bottom: 6px; }
.tag-filter { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--purple-xl); background: #1a1430; border: 1px solid #3a2a66; padding: 3px 10px; border-radius: 999px; }
.empty { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; padding: 40px 20px; color: var(--tx-dim); }
.empty .ic { color: var(--purple-l); opacity: .8; }
.empty p { margin: 4px 0 0; font-weight: 600; color: var(--tx); }

/* ---- sheet grid: one .patch-table per position ----
   One column by default, so the stack of tables reads as the single table it used to be.
   Two columns on a wide screen (further down). The repeated header rows are collapsed to
   nothing rather than removed: table-layout: fixed reads its column widths off the FIRST
   row, and if the header went display:none that would be the position header's colspan
   cell, which would hand every column an equal share. */
.sheet-grid { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; }
.sheet-grid > .patch-table + .patch-table thead th {
  padding: 0; border: 0; height: 0; font-size: 0; line-height: 0; color: transparent;
}

/* ---- two bars side by side ----
   1800, not 1700: measured. A half-width table needs ~636px before its columns drop under
   their own min-content (the address cell alone has a 63px floor, the gel input 78px), and
   with the 1800px shell and the 380px rail the sheet column only clears that from a 1800px
   window up. Below it the grid stays single column, which is the layout it always had.
   Standard mode only: Tour mode's typed universe + address + lock need 108px of address
   column, which no half-width table here can give, so it keeps the full width.
   The columns are re-proportioned for the narrower table: the fixture name gives back what
   the fixed-size controls need, so nothing overflows its cell. */
@media screen and (min-width: 1800px) {
  body:not(.advanced) .sheet-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 24px; }
  /* a lone bar should not sit in half a card */
  body:not(.advanced) .sheet-grid:has(> .patch-table:only-child) { grid-template-columns: minmax(0, 1fr); }
  /* each column is its own list, so each table shows its header again */
  body:not(.advanced) .sheet-grid > .patch-table + .patch-table thead th {
    padding: 8px 6px; border-bottom: 1px solid var(--line-2); height: auto;
    font-size: 10.5px; line-height: 1.5; color: var(--tx-faint);
  }
  body:not(.advanced) .sheet-card { padding: 20px 12px; }
  body:not(.advanced) .patch-table thead th { padding: 8px 6px; }
  body:not(.advanced) .patch-table td { padding: 10px 6px; }
  body:not(.advanced) .patch-table th.c-n, body:not(.advanced) .patch-table td.c-n { width: 8.8%; }
  body:not(.advanced) .patch-table th.c-chan, body:not(.advanced) .patch-table td.c-chan { width: 10%; }
  body:not(.advanced) .patch-table th.c-gel, body:not(.advanced) .patch-table td.c-gel { width: 12.6%; }
  body:not(.advanced) .patch-table th.c-mode, body:not(.advanced) .patch-table td.c-mode { width: 11.3%; }
  body:not(.advanced) .patch-table th.c-uni, body:not(.advanced) .patch-table td.c-uni { width: 7.2%; }
  body:not(.advanced) .patch-table th.c-addr, body:not(.advanced) .patch-table td.c-addr { width: 10.4%; }
  body:not(.advanced) .patch-table th.c-ch, body:not(.advanced) .patch-table td.c-ch { width: 12.6%; }
  body:not(.advanced) .patch-table th.c-x, body:not(.advanced) .patch-table td.c-x { width: 6.6%; }
}

/* table-layout: fixed, because the sheet is one table per position now (see .sheet-grid).
   Auto layout sizes every table to its own content, so the columns stepped between one bar
   and the next. The percentages below are the auto-layout widths measured on the seeded
   example at the 760px default table width, which is why a single-column sheet still lands
   pixel for pixel where it used to. The fixture column carries no width on purpose: it takes
   whatever is left, exactly as auto layout gave it. */
.patch-table { width: 100%; border-collapse: collapse; font-size: 13.5px; table-layout: fixed; }
.patch-table thead th { text-align: left; color: var(--tx-faint); font-weight: 700; font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; padding: 8px 10px; border-bottom: 1px solid var(--line-2); }
.patch-table th.c-n, .patch-table td.c-n { width: 8.2%; text-align: center; color: var(--tx-faint); font-variant-numeric: tabular-nums; font-size: 12px; white-space: nowrap; }
.patch-table th.c-chan, .patch-table td.c-chan { width: 10%; text-align: center; }
.patch-table th.c-gel, .patch-table td.c-gel { width: 11.3%; }
.patch-table th.c-mode, .patch-table td.c-mode { width: 12.5%; }
.patch-table th.c-mode { white-space: nowrap; }
/* a fixed column cannot grow to fit a long mode name, so let it wrap rather than spill
   over the universe column (the multi-mode cell is a full-width <select> and clips itself) */
.patch-table td.c-mode { white-space: normal; overflow-wrap: anywhere; }
.patch-table th.c-uni, .patch-table td.c-uni { width: 6.9%; text-align: center; }
.patch-table th.c-addr, .patch-table td.c-addr { width: 9.4%; text-align: right; white-space: nowrap; }
.patch-table th.c-ch, .patch-table td.c-ch { width: 11.3%; text-align: right; white-space: nowrap; color: var(--tx-dim); font-variant-numeric: tabular-nums; }
.patch-table th.c-x, .patch-table td.c-x { width: 6.3%; text-align: right; }
/* Tour mode swaps the universe tag and the address for typed inputs plus a lock, so those
   two columns need more room and the fixture name gives it up. Measured the same way. */
body.advanced .patch-table th.c-mode, body.advanced .patch-table td.c-mode { width: 11.1%; }
body.advanced .patch-table th.c-uni, body.advanced .patch-table td.c-uni { width: 9.5%; }
body.advanced .patch-table th.c-addr, body.advanced .patch-table td.c-addr { width: 15.3%; }
.patch-table td { padding: 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.patch-table .fx-row { transition: background .12s; }
.patch-table .fx-row:hover td { background: rgba(155,77,255,.05); }
.patch-table .fx-row td b { font-weight: 600; }
.patch-table .fx-row.over td { background: rgba(252,165,165,.06); }
.uni-tag { display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 11px; font-weight: 700; background: #1a1430; color: var(--purple-xl); border: 1px solid #3a2a66; font-family: 'Poppins', sans-serif; font-variant-numeric: tabular-nums; }
.addr-num { font-family: 'Poppins', sans-serif; font-weight: 800; font-size: 20px; font-variant-numeric: tabular-nums;
  background: linear-gradient(160deg, #fff, var(--purple-xl)); -webkit-background-clip: text; background-clip: text; color: transparent; }

.pos-row td { padding: 0; border-bottom: 0; }
.pos-head-inner { display: flex; align-items: center; gap: 10px; margin: 20px 0 4px; padding: 0 4px 8px; border-bottom: 1px solid var(--line-2); }
/* NOTE: the rule that used to sit here, .pos-group:first-child .pos-head-inner { margin-top: 6px },
   never matched: thead is the table's first child, so the tbody is never :first-child. Every
   position header has always taken the 20px above, and it still does. Left out rather than
   revived: reviving it would move every bar 14px and that is a look change, not this phase. */
.pos-head-inner .dot { width: 11px; height: 11px; border-radius: 3px; box-shadow: 0 0 0 3px rgba(255,255,255,.06); flex: none; }
/* colour dot is a real button opening a swatch popover; padding buys the 24px+ hit area */
.dot-wrap { position: relative; display: inline-flex; flex: none; }
.dot-btn { border: 0; padding: 7px; margin: -7px; background-clip: content-box !important; cursor: pointer; box-sizing: content-box; }
.dot-btn:hover, .dot-btn:focus-visible { box-shadow: 0 0 0 3px rgba(255,255,255,.22); outline: none; }
.dot-pop { position: absolute; z-index: 30; top: calc(100% + 8px); left: -6px; display: flex; flex-direction: column; gap: 10px;
  padding: 12px; background: var(--el, #1d1430); border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  box-shadow: 0 12px 32px rgba(0,0,0,.45); min-width: 196px; }
.dot-pop-swatches { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.dot-swatch { width: 28px; height: 28px; border-radius: 8px; border: 2px solid transparent; cursor: pointer; padding: 0; }
.dot-swatch:hover, .dot-swatch:focus-visible { border-color: rgba(255,255,255,.7); outline: none; }
.dot-swatch.active { border-color: #fff; }
.dot-pop-row { display: flex; gap: 8px; }
.dot-pop-row .btn { flex: 1; justify-content: center; }
.dot-custom-lbl { position: relative; overflow: hidden; cursor: pointer; }
.dot-custom-in { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.print-only-dot { display: none; }
.pos-head-inner .pos-name { font-family: 'Poppins', sans-serif; font-size: 15.5px; font-weight: 700; }
.pos-spacer { flex: 1; }
.reorder { display: inline-flex; gap: 2px; }

.icon-btn { appearance: none; cursor: pointer; border: 1px solid transparent; background: transparent; color: var(--tx-faint);
  width: 28px; height: 28px; display: grid; place-items: center; border-radius: 8px;
  transition: background .14s, border-color .14s, color .14s; }
.icon-btn:hover:not(:disabled) { color: #fff; background: var(--el-2); border-color: var(--line-2); }
.icon-btn:disabled { opacity: .3; cursor: not-allowed; }

.actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
/* chunked action groups: export / files / danger read as three clusters, not 8 flat pills */
.act-group { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.act-group + .act-group { padding-left: 14px; border-left: 1px solid var(--line-2); }
.act-group .exp-beta { margin-left: 6px; }
.exp-beta-note { display: flex; align-items: center; gap: 8px; padding: 9px 12px; font-size: 13px; color: var(--tx);
  background: var(--el); border: 1px dashed color-mix(in srgb, var(--warn) 55%, transparent); border-radius: var(--radius-sm); }
.exp-beta-note .ic { color: var(--warn); flex: none; }

/* conflict / clash signalling: a doubled-up address is allowed, but it reads RED everywhere */
.stats .stat.conflict b { background: none; -webkit-text-fill-color: var(--bad); color: var(--bad); }
.fx-row.clash td { background: rgba(248,113,113,.10) !important; }
.fx-row.clash td:first-child { box-shadow: inset 3px 0 0 0 var(--bad); }
.fx-row.clash .addr-num { background: none; -webkit-text-fill-color: var(--bad); color: var(--bad); }
.fx-row.clash .addr-edit { border-color: var(--bad); color: var(--bad); background: var(--bad-bg); }
.fx-row.clash .uni-tag, .fx-row.clash .uni-edit-wrap { border-color: #5a1f25; color: var(--bad); background: var(--bad-bg); }
.fx-row.clash input.uni-edit { color: var(--bad); }
.uni-seg.clash { outline: 1px solid #fff; outline-offset: -1px; }

/* optional hand-placement on add: typed universe number + typed start address */
.addr-add-row { display: flex; align-items: center; gap: 8px; }
/* pro fields (fixture ID + placement) fold behind a disclosure; summary mirrors live values */
.adv-fields { border: 1px solid var(--line-2); border-radius: var(--radius-sm); background: var(--bg); }
.adv-sum { display: flex; align-items: center; gap: 8px; padding: 10px 12px; cursor: pointer; list-style: none;
  font-size: 13px; color: var(--tx); user-select: none; }
.adv-sum::-webkit-details-marker { display: none; }
.adv-sum::after { content: ''; width: 7px; height: 7px; border-right: 2px solid var(--tx-3, #888); border-bottom: 2px solid var(--tx-3, #888);
  transform: rotate(45deg); margin-left: auto; transition: transform .15s ease; flex: none; }
.adv-fields[open] .adv-sum::after { transform: rotate(-135deg); }
.adv-sum .ic { color: var(--purple-l); flex: none; }
.adv-sum-val { margin-left: 4px; font-size: 12px; color: var(--tx-3, #999); font-variant-numeric: tabular-nums; }
.adv-fields > .field { padding: 0 12px 12px; }
.adv-fields .hint { margin-top: 6px; }
.uni-add-wrap { display: inline-flex; align-items: center; gap: 2px; padding: 0 4px 0 12px; background: var(--bg); border: 1px solid var(--line-2);
  border-radius: 11px; color: var(--purple-xl); font-family: 'Poppins', sans-serif; transition: opacity .14s, border-color .14s; cursor: text; }
.uni-add-wrap > b { font-size: 13px; font-weight: 700; }
.uni-add-wrap.dim { opacity: .45; }
.uni-add-wrap:focus-within { border-color: var(--purple-l); }
input.uni-add { width: 42px; padding: 9px 4px; font-size: 13px; font-weight: 700; font-family: 'Poppins', sans-serif; color: var(--purple-xl);
  background: transparent; border: 0; text-align: left; font-variant-numeric: tabular-nums; }
input.uni-add:focus-visible { outline: none; box-shadow: none; }
input.uni-add::-webkit-outer-spin-button, input.uni-add::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.addr-add-in { width: 100px; }
.same-addr-lbl { margin-top: 8px; }
.same-addr-lbl span { line-height: 1.4; }

/* per-position pin control (manual addressing) */
.pin-ctl { display: inline-flex; align-items: center; gap: 6px; }
.pin-lbl { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--tx-faint); font-weight: 600; }
.pin-lbl .ic { color: var(--tx-faint); }
input.pin-uni { width: 64px; padding: 4px 8px; font-size: 12px; font-weight: 600; text-align: center; }
.pin-addr { width: 64px; padding: 4px 8px; font-size: 12px; text-align: center; }
/* type=number reserves shadow-DOM spinner width INSIDE the padding box, so the placeholder
   clipped ("Aut") at the 16px phone size. Drop the spinner and size to the word. */
input.pin-uni, input.pin-addr { -webkit-appearance: none; appearance: none; min-width: 5.5ch; }
input.pin-uni::-webkit-outer-spin-button, input.pin-uni::-webkit-inner-spin-button,
input.pin-addr::-webkit-outer-spin-button, input.pin-addr::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* inline mode select on a row (blends in until focused) */
.mode-select { appearance: none; background: transparent; border: 1px solid transparent; color: var(--tx-dim); font: inherit; font-size: 12.5px;
  padding: 3px 22px 3px 7px; border-radius: 7px; cursor: pointer; max-width: 100%; min-width: 58px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239aa0b4' stroke-width='2' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center; }
.mode-select:hover { border-color: var(--line-2); color: var(--tx); }
.mode-select:focus { border-color: var(--purple-l); color: var(--tx); }

/* paperwork columns: Unit # (assigns the order), console Channel, Gel colour.
   element+class selectors so they beat app.css `input[type='number']` (the specificity trap) */
input.unit-edit { width: 40px; font: inherit; font-size: 12.5px; font-weight: 700; text-align: center; color: var(--tx-dim); font-variant-numeric: tabular-nums;
  background: transparent; border: 1px solid transparent; border-radius: 7px; padding: 4px 2px; transition: all .14s; }
input.unit-edit:hover { border-color: var(--line-2); color: var(--tx); }
input.unit-edit:focus { border-color: var(--purple-l); color: var(--tx); background: var(--bg); }
input.unit-edit::-webkit-outer-spin-button, input.unit-edit::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* channel + gel read as paper form fields: a dashed "write here" underline until filled */
input.chan-edit { width: 48px; text-align: center; font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 13.5px; font-variant-numeric: tabular-nums; }
input.gel-edit { width: 66px; font: inherit; font-size: 12.5px; }
input.chan-edit, input.gel-edit { color: var(--tx); background: transparent; border: 1px solid transparent; border-bottom: 1px dashed var(--line-2); border-radius: 0; padding: 4px 5px; transition: all .14s; }
input.chan-edit:hover, input.gel-edit:hover { border-bottom-color: var(--purple-l); }
input.chan-edit:focus, input.gel-edit:focus { border-color: var(--purple-l); border-bottom-style: solid; border-radius: 7px; background: var(--bg); }
input.chan-edit::-webkit-outer-spin-button, input.chan-edit::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* visible rename pencil beside each position name */
.rename-btn { width: 24px; height: 24px; min-width: 24px; min-height: 24px; margin-left: -4px; }

/* inline rename input */
.rename-in { font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 15.5px; padding: 2px 8px; width: 180px; }

/* undo / status toast */
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 200;
  display: flex; align-items: center; gap: 16px; padding: 11px 16px; border-radius: 12px;
  background: var(--card-2); border: 1px solid var(--line-2); box-shadow: 0 14px 40px -10px rgba(0,0,0,.8); font-size: 13.5px; }
.toast-undo { appearance: none; cursor: pointer; border: 0; background: transparent; color: var(--purple-xl); font: inherit; font-weight: 700; }
.toast-undo:hover { text-decoration: underline; }

/* help button + guided tour */
.help-btn { display: inline-flex; align-items: center; gap: 5px; appearance: none; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600;
  padding: 5px 11px; border-radius: 999px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx-dim); transition: all .14s; }
.help-btn:hover { color: #fff; border-color: var(--purple-l); }
.help-btn .ic { color: var(--purple-xl); }

.tour-overlay { position: fixed; inset: 0; z-index: 300; }
/* Same wash the spotlight paints, for the steps that have nothing to spotlight. */
.tour-overlay.dim { background: rgba(8, 8, 14, .66); }
/* The library modal (z 250) sits under the tour overlay, which also swallows every click
   through its inset: 0. Pause the tour rather than stack them; it returns on close. */
body.lib-open .tour-overlay { display: none; }
.tour-spot { position: fixed; display: none; border-radius: 12px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(8, 8, 14, .66), 0 0 0 2px var(--purple-l), 0 0 24px 4px rgba(155, 77, 255, .5);
  transition: top .25s cubic-bezier(.4,0,.2,1), left .25s cubic-bezier(.4,0,.2,1), width .25s, height .25s; }
.tour-card { position: fixed; width: 330px; max-width: calc(100vw - 28px); z-index: 301; padding: 18px;
  background: linear-gradient(180deg, var(--card-2), var(--card)); border: 1px solid var(--line-2); border-radius: 14px; box-shadow: 0 20px 60px -12px rgba(0,0,0,.85); }
.tour-card:focus { outline: none; }
.tour-step { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--purple-xl); }
.tour-card h2, .tour-card h4 { margin: 7px 0 6px; font-family: 'Poppins', sans-serif; font-size: 17px; font-weight: 700; letter-spacing: -.01em; }
.tour-card p { margin: 0; color: var(--tx-dim); font-size: 13.5px; line-height: 1.55; }
.tour-actions { display: flex; align-items: center; gap: 8px; margin-top: 16px; }
@media (prefers-reduced-motion: reduce) { .tour-spot { transition: none; } }

@media (max-width: 700px) { .pin-lbl { display: none; } }

/* mid widths (tablet portrait through small desktop): slim the sheet's paddings so the
   9-column table (Tour mode needs ~720px at full padding) always fits without scrolling.
   AFTER the base .patch-table rules: equal specificity, so source order decides. */
@media (min-width: 741px) and (max-width: 1170px) {
  .sheet-card, .summary-card { padding: 16px 10px; }
  .patch-table thead th { padding: 8px 6px; }
  .patch-table td { padding: 10px 6px; }
}

/* ===================== phones: proper mobile layout =====================
   740px, not 560: with the Unit/Channel/Gel columns the full table needs ~700px
   incl. card padding, so everything below iPad-portrait (768) reads as cards */
@media (max-width: 740px) {
  .mode-picker { font-size: 16px; min-height: 44px; }
  .btn.sm.hist-btn { min-height: 44px; padding: 10px 14px; }
  .sheet-card .card-head { flex-wrap: wrap; }
  .hist-btns { margin-left: 0; flex-basis: 100%; }
  .hist-btns .hist-btn { flex: 1; justify-content: center; }
  /* 16px inputs so iOS doesn't zoom the page on focus (match app.css attribute-selector specificity) */
  input[type='text'], input[type='number'], input[type='date'], select { font-size: 16px; }
  .addr-box { font-size: 26px; }

  .summary-card, .add-card, .settings-card, .meta-card { padding: 16px 14px; }
  /* The phone sheet already turns every fixture into its own bordered card, so the sheet's
     own frame was a box drawn around a column of boxes: 58px of a 390px screen went to
     three nested gutters before any content. Drop the outer frame and let the rows be the
     cards; the head keeps the shell's gutter, so nothing else moves. */
  .sheet-card { padding: 16px 0; background: none; border: 0; box-shadow: none; }
  .sheet-card > .card-head, .sheet-card > .empty, .sheet-card > .sheet-std-cta,
  .sheet-card > .sheet-adv-hint, .sheet-card > .universe-track { margin-inline: 2px; }
  .studio-grid { gap: 14px; }
  .stats { gap: 18px; }
  .stats .stat b { font-size: 28px; }

  /* ≥44px touch targets (Apple HIG / Material). min-* defeats flex min-content shrink. */
  .icon-btn { width: 42px; height: 42px; min-width: 42px; min-height: 42px; }
  .reorder { gap: 4px; }
  .step-btn { width: 44px; height: 44px; min-width: 44px; min-height: 44px; }
  input.qty-in { min-width: 30px; width: 44px; }
  .chip { padding: 10px 15px; }
  .mode-pill { padding: 10px 14px; }
  .uni-tab { padding: 10px 14px; }
  .seg button { padding: 10px 14px; }
  .combo-opt { padding: 12px 10px; }
  .combo-panel { max-height: 52vh; }
  .btn { padding: 12px 16px; }
  /* .btn.sm / .seg.sm button carry (0,2,0)/(0,2,1) base rules in app.css, so the plain .btn and
     .seg button bumps above never reached them: 34px and 29px tall on a phone. Same for the row
     inputs, the mode select and the colour dot (a 25px hit area on an 11px swatch). */
  .btn.sm { padding: 10px 14px; font-size: 13.5px; min-height: 42px; }
  .seg.sm button { padding: 10px 14px; font-size: 13.5px; }
  .help-btn { padding: 11px 14px; }
  /* the swatch's ring is a box-shadow, so widen the hit area with a pseudo-element, not padding */
  .dot-btn { position: relative; }
  .dot-btn::after { content: ''; position: absolute; inset: -9px; }
  input.unit-edit, input.chan-edit, input.gel-edit { padding: 9px 6px; }
  .mode-select { padding: 10px 26px 10px 9px; font-size: 13.5px; background-position: right 8px center; }
  /* the count field fills its 52px stepper so a tap anywhere between the arrows focuses it */
  input.qty-in { height: 44px; }
  /* click-to-rename position name: pad the hit area without moving the text */
  .pos-head-inner .pos-name { padding: 9px 6px; margin: -9px -6px; }
  .show-bar-inner .show-switch { padding: 9px 11px 9px 13px; } /* (0,2,0): the base rule sits after this block */
  .pin-uni, .pin-addr { padding: 9px 10px; }

  /* patch sheet: table -> stacked cards (no horizontal scroll, no cramped columns).
     Actions sit top-right beside the name; universe/address/channels share row two;
     a multi-mode fixture gets its mode picker on a third row. */
  /* block, not grid: the position headers' top margins collapse through a block wrapper
     exactly as they did when the sheet was one table, so the card spacing is unchanged */
  .sheet-grid { display: block; }
  .patch-table, .patch-table tbody, .pos-group { display: block; min-width: 0; }
  .patch-table thead { display: none; }
  .pos-row, .pos-row > td { display: block; padding: 0; border: 0; }
  .fx-row { display: grid; align-items: center; column-gap: 10px; row-gap: 8px;
    grid-template-columns: max-content max-content minmax(0, 1fr);
    grid-template-areas: "name name name" "uni addr ch" "unit chan gel" "mode mode mode";
    border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; margin: 0 0 10px; }
  .fx-row td { padding: 0; border: 0; min-width: 0; }
  /* the table's fixed column widths (td.c-uni 52px, td.c-x 30px, ...) are (0,2,1) rules for the desktop
     table; on cards they clipped the unit input into the ID label and pushed the delete button out of
     the card. Same specificity, later in the file, so this wins. */
  .patch-table .fx-row td, body.advanced .patch-table .fx-row td { width: auto; }
  /* Tour mode: the address + lock cluster needs the room, so the DMX range takes its own line */
  body.advanced .fx-row { grid-template-areas: "name name name" "uni addr addr" "ch ch ch" "unit chan gel" "mode mode mode"; }
  /* name and actions share the top row: the buttons no longer own a fourth column (which starved
     the paperwork columns and let a long name run under the icons); the padding keeps them apart */
  .fx-row .c-fx { grid-area: name; padding-right: 100px; min-height: 42px; display: flex; align-items: center; }
  .fx-row .c-fx b { font-size: 15px; }
  .fx-row .c-uni { grid-area: uni; }
  .fx-row .c-addr { grid-area: addr; display: flex; align-items: center; gap: 6px; }
  .fx-row .c-addr::before { content: 'Addr'; font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--tx-faint); }
  body.advanced .fx-row .c-addr::before { display: none; } /* tour mode: the input + lock speak for themselves */
  .fx-row .c-ch { grid-area: ch; justify-self: end; }
  .fx-row .c-ch::before { content: 'DMX '; color: var(--tx-faint); }
  /* paperwork row: unit # + console channel + gel colour, each with a tiny label */
  .fx-row .c-n, .fx-row .c-chan, .fx-row .c-gel { display: flex; align-items: center; gap: 6px; width: auto; }
  .fx-row .c-n::before, .fx-row .c-chan::before, .fx-row .c-gel::before {
    font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--tx-faint); }
  .fx-row .c-n { grid-area: unit; }
  .fx-row .c-n::before { content: 'Unit'; }
  .fx-row .c-chan { grid-area: chan; }
  .fx-row .c-chan::before { content: 'ID'; }
  .fx-row .c-gel { grid-area: gel; min-width: 0; }
  .fx-row .c-gel::before { content: 'Gel'; }
  .fx-row .c-gel input.gel-edit { flex: 1; min-width: 36px; width: auto; } /* 72px pushed the row through the card padding at 320 */
  /* no hover on touch: give the unit number the same "editable" dashed cue as CH/GEL */
  input.unit-edit { width: 48px; flex: none; border-radius: 0; border-bottom: 1px dashed var(--line-2); }
  .fx-row .c-gel { min-width: 0; }
  input.chan-edit { width: 58px; flex: none; }
  input.uni-edit { width: 40px; }
  input.pin-uni { padding: 9px 10px; }
  .fx-row .c-x { grid-area: name; justify-self: end; align-self: start; display: flex; gap: 8px; }
  /* Tour mode targets */
  .addr-lock { width: 40px; height: 40px; }
  input.addr-edit { padding: 8px 6px; }
  input.uni-edit { padding: 7px 2px; }
  .lock-btn { padding: 10px 12px; min-height: 40px; }
  /* single-mode fixtures hide the mode cell; multi-mode ones keep their picker on the card */
  .fx-row .c-mode, .patch-table thead .c-mode { display: none; }
  /* solid, not dashed: the unit/ch/gel underlines above are already dashed "write here" cues, and two dashed rules 16px apart read as a mistake */
  .fx-row .c-mode:has(.mode-select) { display: block; grid-area: mode; border-top: 1px solid var(--line); padding-top: 8px; }
  .patch-table .fx-row:hover td { background: none; } /* sticky touch hover would leave grey cells behind after a tap */
  .fx-row.clash { border-color: var(--bad); }
  .fx-row.clash td { background: none !important; }
  .fx-row.clash td:first-child { box-shadow: none; } /* the red edge stripe belongs to the table layout */
  /* state reads on the whole card on phones, never as per-cell stripes */
  .fx-row.locked { border-color: var(--purple-l); background: linear-gradient(180deg, rgba(155,77,255,.07), transparent); }
  .fx-row.locked td { background: none !important; }
  .fx-row.unplaced { border-color: var(--bad); background: rgba(252,165,165,.05); }
  .fx-row.unplaced td { background: none !important; }

  /* universe summary rows: title + lock on line one, the used/free meta on its own line */
  .uni-row-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; row-gap: 3px; }
  .uni-row-head b { grid-column: 1; grid-row: 1; white-space: nowrap; }
  .uni-row-head > .muted { grid-column: 1 / -1; grid-row: 2; }
  .uni-row-head .pos-spacer { display: none; }
  .uni-row-head .lock-btn { grid-column: 2; grid-row: 1; justify-self: end; }

  /* position header: drop the controls to their own line so they never overflow */
  .pos-head-inner { flex-wrap: wrap; row-gap: 10px; }
  .pos-spacer { flex-basis: 100%; height: 0; }
  .pin-ctl { flex-wrap: wrap; }

  /* toast clears the home-indicator / notch safe areas */
  .toast { left: 14px; right: 14px; transform: none; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
  .actions { gap: 8px; }
}

/* =====================================================================
   SHOW BAR: saved shows (a touring rig book)
   ===================================================================== */
.show-bar { margin-bottom: 14px; }
.show-bar-inner { display: flex; align-items: center; gap: 12px;
  background: linear-gradient(180deg, var(--card-2), var(--card)); border: 1px solid var(--line-2); border-radius: 13px; padding: 9px 12px; }
.show-bar-lbl { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--tx-faint); }
.show-bar-lbl .ic { color: var(--purple-xl); }
.show-switch-wrap { position: relative; }
.show-switch { appearance: none; cursor: pointer; font: inherit; display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 11px 7px 13px; border-radius: 10px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx); transition: all .14s; max-width: min(60vw, 360px); }
.show-switch:hover { border-color: var(--purple-l); }
.show-switch.open { border-color: var(--purple-l); box-shadow: inset 0 0 0 1px rgba(155,77,255,.35); }
.show-switch b { font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.show-switch-meta { flex: none; padding: 1px 7px; border-radius: 6px; background: var(--bg); border: 1px solid var(--line); font-variant-numeric: tabular-nums; }
.show-switch .ic { color: var(--tx-dim); flex: none; }
.show-rename { font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 14.5px; padding: 6px 11px; width: min(60vw, 300px); }
.new-show-btn { flex: none; }

.show-menu { position: absolute; top: calc(100% + 7px); left: 0; z-index: 60; width: 320px; max-width: calc(100vw - 32px);
  background: var(--card-2); border: 1px solid var(--line-2); border-radius: 13px; box-shadow: 0 20px 56px -14px rgba(0,0,0,.85); overflow: hidden; }
.show-list { max-height: 46vh; overflow-y: auto; padding: 6px; }
.show-item { width: 100%; appearance: none; cursor: pointer; font: inherit; text-align: left; display: grid; grid-template-columns: 18px 1fr auto; align-items: center; gap: 9px;
  padding: 9px 10px; border-radius: 9px; border: 0; background: transparent; color: var(--tx); transition: background .12s; }
.show-item:hover { background: var(--el); }
.show-item.active { background: linear-gradient(90deg, rgba(155,77,255,.14), transparent); }
.show-item-check { display: inline-flex; justify-content: center; color: var(--purple-xl); }
.show-item-name { font-weight: 600; font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.show-item-meta { flex: none; font-variant-numeric: tabular-nums; }
.show-menu-acts { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; padding: 7px; border-top: 1px solid var(--line); background: var(--card); }
.show-act { appearance: none; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 600; display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 10px; border-radius: 8px; border: 0; background: transparent; color: var(--tx-dim); transition: all .12s; }
.show-act:hover { background: var(--el); color: var(--tx); }
.show-act .ic { color: var(--tx-faint); }
.show-act:hover .ic { color: var(--purple-xl); }
.show-act.danger:hover { background: var(--bad-bg); color: var(--bad); }
.show-act.danger:hover .ic { color: var(--bad); }

/* custom-fixture quick-save toggle + browse button */
.save-custom-lbl { display: inline-flex; align-items: center; gap: 8px; margin-top: 10px; cursor: pointer; font-size: 12.5px; color: var(--tx-dim); }
.save-custom-lbl input { width: 16px; height: 16px; accent-color: var(--purple-l); cursor: pointer; }
.browse-lib-btn { margin-top: 10px; width: 100%; justify-content: center; color: var(--tx-dim); }
.browse-lib-btn:hover { color: #fff; }
/* Hire fleet: the mark that says whose fixtures these are, and the action that turns a patch into a quote. */
.fleet-chip { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px; font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--purple-xl); background: rgba(125, 40, 219, .18); border: 1px solid rgba(155, 77, 255, .55); vertical-align: 2px; white-space: nowrap; }
.fleet-link { font-size: 12.5px; color: var(--purple-xl); text-decoration: underline; text-underline-offset: 3px; align-self: center; margin-left: 4px; }
.btn.hire { border-color: rgba(155, 77, 255, .7); color: var(--purple-xl); }
.btn.hire:hover:not([disabled]) { background: rgba(125, 40, 219, .22); border-color: var(--purple-l); }
.btn.hire[disabled] { opacity: .45; cursor: not-allowed; }
.combo-opt.request { border-top: 1px solid var(--line); margin-top: 4px; text-decoration: none; color: inherit; }
.combo-opt.request .co-name { color: var(--purple-xl); }
.combo-opt.browse { border-top: 1px solid var(--line); margin-top: 4px; }
.combo-opt.browse .co-name { display: inline-flex; align-items: center; gap: 7px; color: var(--purple-xl); font-weight: 600; }
.combo-opt.browse .co-name .ic { color: var(--purple-xl); }

/* =====================================================================
   FIXTURE LIBRARY MODAL: console-style browse-by-brand
   ===================================================================== */
.lib-modal { position: fixed; inset: 0; z-index: 250; display: grid; place-items: center; padding: 16px; }
.lib-backdrop { position: fixed; inset: 0; background: rgba(6,6,12,.74); backdrop-filter: blur(3px); }
.lib-panel { position: relative; z-index: 1; width: min(1080px, 100%); height: min(86vh, 820px); display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--card-2), var(--card)); border: 1px solid var(--line-2); border-radius: 18px; box-shadow: 0 40px 100px -24px rgba(0,0,0,.85); overflow: hidden; }
.toast { z-index: 400; }
body.lib-open { overflow: hidden; }

.lib-head { display: flex; align-items: center; gap: 12px; padding: 16px 18px; border-bottom: 1px solid var(--line); }
.lib-title { display: flex; align-items: center; gap: 9px; flex: 1; }
.lib-title .ic { color: var(--purple-xl); }
.lib-title b { font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 16px; }
.lib-count { margin-left: 4px; }
.lib-close { flex: none; }

.lib-tools { display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.lib-search { position: relative; flex: 1; min-width: 220px; }
.lib-search .combo-ic { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--tx-faint); pointer-events: none; display: inline-flex; }
.lib-search input.lib-search-input { width: 100%; padding-left: 40px; }
.lib-source { display: inline-flex; gap: 4px; background: var(--bg); border: 1px solid var(--line-2); border-radius: 11px; padding: 4px; }
.lib-src-btn { appearance: none; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 600; padding: 7px 13px; border-radius: 8px; border: 0; background: transparent; color: var(--tx-dim); transition: all .14s; white-space: nowrap; }
.lib-src-btn:hover { color: var(--tx); }
.lib-src-btn.active { background: linear-gradient(145deg, var(--purple-l), var(--purple)); color: #fff; box-shadow: 0 3px 12px -5px rgba(125,40,219,.9); }

.lib-body { flex: 1; min-height: 0; display: grid; grid-template-columns: 216px 1fr; }
.lib-brands { border-right: 1px solid var(--line); overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.lib-brands.hidden { display: none; }
.lib-brands.hidden + .lib-list { grid-column: 1 / -1; }
.lib-brand { appearance: none; cursor: pointer; font: inherit; text-align: left; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 9px 11px; border-radius: 9px; border: 0; background: transparent; color: var(--tx-dim); font-size: 13px; font-weight: 500; transition: all .12s; }
.lib-brand:hover { background: var(--el); color: var(--tx); }
.lib-brand.active { background: linear-gradient(90deg, rgba(155,77,255,.16), transparent); color: #fff; font-weight: 600; }
.lib-brand-n { flex: none; font-size: 11px; color: var(--tx-faint); font-variant-numeric: tabular-nums; }
.lib-brand.active .lib-brand-n { color: var(--purple-xl); }

.lib-list { overflow-y: auto; padding: 16px 18px; }
/* align-items:start keeps each card its natural height, so mode chips sit right under the
   fixture name instead of being pushed to the bottom of the tallest card in the row */
.lib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: 12px; align-items: start; }
.lib-card { background: var(--card); border: 1px solid var(--line); border-radius: 13px; padding: 12px 13px; display: flex; flex-direction: column; gap: 10px; transition: border-color .14s; }
.lib-card:hover { border-color: var(--line-2); }
.lib-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.lib-card-name { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lib-card-brand { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--tx-faint); font-weight: 700; }
.lib-card-name b { font-weight: 600; font-size: 14px; line-height: 1.25; }
.lib-card-acts { display: inline-flex; gap: 2px; flex: none; }
.lib-modes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; }
.lib-mode { appearance: none; cursor: pointer; font: inherit; text-align: left; display: inline-flex; flex-direction: column; gap: 0;
  padding: 6px 11px; border-radius: 9px; border: 1px solid var(--line-2); background: var(--el); color: var(--tx); transition: all .12s; }
.lib-mode:hover { border-color: var(--purple-l); background: linear-gradient(180deg, #241640, var(--el)); }
.lib-mode b { font-weight: 600; font-size: 12.5px; max-width: 150px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lib-mode small { color: var(--tx-dim); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.lib-mode.added { border-color: var(--good, #7CFFB2); background: rgba(124,255,178,.16); animation: lib-pop .3s ease; }
@keyframes lib-pop { 0% { transform: scale(1); } 40% { transform: scale(1.06); } 100% { transform: scale(1); } }

.lib-custom-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.lib-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; padding: 56px 20px; color: var(--tx-dim); }
.lib-empty .ic { color: var(--purple-l); opacity: .7; }
.lib-empty p { margin: 4px 0 0; font-weight: 600; color: var(--tx); }
.lib-trunc { margin-top: 14px; text-align: center; }
.fl-empty-acts { display: flex; flex-wrap: wrap; justify-content: center; gap: 9px; margin-top: 14px; }

/* custom-fixture editor */
.lib-editor { max-width: 560px; }
.lib-editor h4 { margin: 0 0 16px; font-family: 'Poppins', sans-serif; font-size: 17px; font-weight: 700; }
.lib-edit-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 16px; }
.lib-edit-row label { display: flex; flex-direction: column; gap: 6px; }
.lib-edit-modes { display: flex; flex-direction: column; gap: 8px; margin: 8px 0 12px; }
.lib-edit-mode { display: flex; align-items: center; gap: 8px; }
.lib-edit-mode input[type='text'] { flex: 1; }
.lib-edit-actions { display: flex; gap: 10px; margin-top: 20px; }

/* export show-file modal (shares the lib-modal shell) */
.exp-panel { width: min(760px, 100%); height: auto; max-height: min(86vh, 820px); }
.exp-body { padding: 18px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }
.exp-strip { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px;
  background: var(--el); border: 1px solid var(--line-2); border-radius: var(--radius-sm); flex-wrap: wrap; }
.exp-renum { display: flex; align-items: center; gap: 8px; }
.exp-start-in { width: 64px; }
.exp-warnings { display: flex; flex-direction: column; gap: 8px; }
.exp-warnings:empty { display: none; }
.exp-warn { display: flex; align-items: flex-start; gap: 8px; padding: 9px 12px; font-size: 13px;
  background: var(--warn-bg); border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent); border-radius: var(--radius-sm); color: var(--tx); }
.exp-warn .ic { color: var(--warn); flex: none; margin-top: 1px; }
.exp-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.exp-card { display: flex; flex-direction: column; gap: 8px; padding: 14px; background: var(--el);
  border: 1px solid var(--line-2); border-radius: var(--radius-sm); }
.exp-card.primary { border-color: var(--purple-l); box-shadow: var(--glow); }
.exp-card p { margin: 0; flex: 1; }
.exp-card .btn { align-self: flex-start; }
.exp-card-head { display: flex; align-items: center; gap: 8px; }
.exp-card-head b { font-family: 'Poppins', sans-serif; font-size: 14.5px; }
.exp-ext { margin-left: auto; font-size: 11px; color: var(--tx-faint); font-family: ui-monospace, monospace; }
.exp-beta { font-size: 10px; font-weight: 700; letter-spacing: .08em; color: var(--warn); border: 1px solid var(--warn);
  border-radius: 5px; padding: 1px 5px; }
.exp-share { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; border-top: 1px solid var(--line); padding-top: 12px; }

/* restored-from-QR banner */
.restore-banner { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; padding: 12px 14px;
  background: var(--ok-bg); border: 1px solid color-mix(in srgb, var(--ok) 40%, transparent); border-radius: var(--radius-sm); }
.restore-banner > .ic { color: var(--ok); flex: none; }
.restore-banner .restore-msg { flex: 1 1 240px; font-size: 13.5px; }

@media (max-width: 720px) {
  .lib-modal { padding: 0; }
  .lib-panel { width: 100%; height: 100%; border-radius: 0; border: 0; }
  .exp-panel { height: auto; max-height: 100%; }
  .exp-cards { grid-template-columns: 1fr; }
  .lib-tools { gap: 10px; }
  .lib-source { width: 100%; }
  .lib-src-btn { flex: 1; text-align: center; padding: 10px 13px; }
  .lib-brand { padding: 10px 12px; min-height: 42px; }
  .lib-body { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .lib-brands { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); gap: 6px; }
  .lib-brands.hidden + .lib-list { grid-row: 1 / -1; }
  .lib-brand { flex: none; }
  .lib-grid { grid-template-columns: 1fr; }
  .lib-mode b { max-width: none; }
}

/* =====================================================================
   branded print patch sheet
   ===================================================================== */
.print-only { display: none; }
.print-header { align-items: center; gap: 16px; padding-bottom: 14px; margin-bottom: 18px; border-bottom: 2px solid #111; }
.print-header .print-logo { width: 56px; height: 56px; object-fit: contain; }
.print-header .print-title { flex: 1; }
.print-header .print-title b { font-family: 'Poppins', sans-serif; font-size: 21px; font-weight: 800; display: block; }
.print-header .print-meta { font-size: 12px; color: #444; margin-top: 3px; }
.print-header .print-brand { text-align: right; line-height: 1.15; }
.print-header .print-brand b { font-family: 'Poppins', sans-serif; font-size: 15px; letter-spacing: .04em; display: block; }
.print-header .print-brand span { font-size: 10px; color: #666; text-transform: uppercase; letter-spacing: .12em; }
/* scan-to-reopen QR: physical mm so print scaling can't shrink it below scannable size */
.print-qr { display: flex; flex-direction: column; align-items: center; gap: 1mm; margin-left: 6mm; }
.print-qr:empty { display: none; }
.print-qr svg { width: 22mm; height: 22mm; }
.print-qr.dense svg { width: 30mm; height: 30mm; } /* full state-in-URL fallback: denser code, print larger */
.print-qr .print-qr-cap { font-size: 7.5px; color: #666; max-width: 30mm; text-align: center; overflow-wrap: anywhere; }
.print-footer { margin-top: 16px; padding-top: 10px; border-top: 1px solid #ccc; font-size: 10px; color: #666; text-align: center; }

@media print {
  @page { margin: 10mm; }
  body { background: #fff !important; color: #111; }
  .kd-ambient, .topbar, .meta-card, .studio-side, .actions, .uni-tabs, .footer-note, .no-print, .tour-overlay, .toast, .lib-modal, .show-bar { display: none !important; }
  .shell { max-width: none; padding: 0; }
  .studio-grid { grid-template-columns: 1fr; gap: 0; }
  .print-only { display: flex; }
  .print-footer { display: block; }
  .card { box-shadow: none; border: 0; background: #fff; color: #111; padding: 0; margin: 0 0 12px; }
  /* break-inside on a card only helps when the card can fit a page; the sheet card is
     many pages tall, so the rule lives on the summary card alone */
  .summary-card { break-inside: avoid; }
  /* ---- page fragmentation (support matrix, verified 2026-08) ----
     .patch-table tr { break-inside: avoid }  rows never split: Chromium + Firefox
     thead { display: table-header-group }    header repeats per page: Chromium + Firefox;
                                              Safari may print it on page 1 only
     .pos-row td { break-after: avoid-page }  position header glued to its first row:
                                              Chromium only; Firefox/Safari ignore it
     Safari may still split rows: that degrades to the pre-compaction behaviour. Do NOT
     "fix" Safari by removing these rules, and keep borders on td/th (never tbody):
     WebKit mishandles collapsed borders across page fragments.
     Deliberately NOT break-inside: avoid on tbody.pos-group: a bar taller than one page
     would force a blank gap and then split anyway. */
  .patch-table thead { display: table-header-group; }
  .patch-table tr { break-inside: avoid; }
  .pos-row td { break-after: avoid-page; }
  /* one column on paper whatever the window was, and every bar's table keeps its own header
     row: that is what makes display: table-header-group repeat it on each page it spans */
  .sheet-grid { display: block; }
  .sheet-grid > .patch-table + .patch-table { margin-top: 12px; }
  .sheet-grid > .patch-table + .patch-table thead th {
    padding: 3px 6px; border-bottom: 1px solid #999; height: auto;
    font-size: 9px; line-height: 1.5; color: #333;
  }
  /* ---- density: the ask is more fixtures per page; hierarchy: address + universe are
     THE numbers read at the rack, so they stay a step bolder while everything else
     absorbs the compaction ---- */
  .patch-table { font-size: 10.5px; }
  .patch-table td { padding: 3px 6px; }
  .patch-table thead th { padding: 3px 6px; font-size: 9px; }
  .pos-head-inner { margin: 10px 0 2px; padding: 0 2px 4px; gap: 8px; }
  .pos-head-inner b.pos-name { font-size: 11.5px; }
  .print-header { margin-bottom: 8px; padding-bottom: 6px; }
  /* each row carries its bar name in the unit cell ("LX2-7") so a position spanning a
     page break keeps its identity, the way real patch sheets do */
  td.c-n::before { content: attr(data-pos) '-'; font-size: 7.5px; color: #888; letter-spacing: .02em; }
  .card-head .ic, .card-head h2, .card-head h3 { color: #333; }
  .stats .stat b, .addr-num { color: #111 !important; -webkit-text-fill-color: #111; background: none; }
  .stats .stat span { color: #555; }
  .uni-tag { background: #eee; color: #333; border-color: #ccc; }
  .patch-table thead th, .pos-head-inner { border-color: #999; color: #333; }
  .patch-table td { border-color: #ddd; }
  .patch-table .fx-row:hover td { background: none; }
  .universe-track { border-color: #bbb; background: #f4f4f7; }
  .uni-row-head b { color: #111; }
  /* printers strip background colours by default; keep the position colour coding */
  .uni-seg, .pos-head-inner .dot, .universe-track { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .print-only-dot { display: inline-block; }
  /* duplicate-channel outline is a screen editing aid, not part of the document */
  .chan-edit.dup { outline: none; }
  /* lift the light-grey on-screen text to print-legible ink */
  .muted, .patch-table td.c-ch, .patch-table td.c-mode span { color: #444; }
  .patch-table thead th.c-ch, .patch-table thead th.c-n { color: #333; }
  .patch-table td.c-n { color: #666; }
  /* lock/clash state is an on-screen editing aid, not part of the printed document */
  .fx-row.locked td, .fx-row.clash td, .fx-row.unplaced td { background: none !important; }
  .fx-row.clash td:first-child { box-shadow: none; }
  .fx-row.clash .addr-num { -webkit-text-fill-color: #111; }
  .fx-row.clash .uni-tag { background: #eee; color: #333; border-color: #ccc; }
  .c-mode { display: table-cell; }
  .mode-select { -webkit-appearance: none; appearance: none; background: none; border: 0; color: #333; padding: 0; }
  /* editable tour-mode controls print as plain values */
  .uni-edit-wrap { background: none !important; border: 0 !important; padding: 0; color: #111; }
  .uni-edit-wrap > b { font-size: 13px; }
  input.uni-edit, input.addr-edit { -webkit-appearance: none; appearance: none; background: none !important; border: 0 !important; padding: 0; color: #111 !important; -webkit-text-fill-color: #111; font-family: 'Poppins', sans-serif; }
  input.uni-edit { font-size: 11px; font-weight: 700; text-align: left; width: 22px; }
  input.addr-edit { font-size: 12.5px; font-weight: 800; text-align: left; width: auto; }
  .addr-num { font-size: 12.5px; font-weight: 800; }
  .uni-tag { font-size: 11px; font-weight: 700; }
  /* paperwork fields (unit # / channel / gel) print as plain ink too */
  input.unit-edit, input.chan-edit, input.gel-edit { -webkit-appearance: none; appearance: none; background: none !important; border: 0 !important; padding: 0; color: #111 !important; -webkit-text-fill-color: #111; font-size: 10px; }
  input.unit-edit { color: #666 !important; -webkit-text-fill-color: #666; text-align: center; width: 30px; }
  input.chan-edit { font-weight: 700; text-align: center; }
}

/* =====================================================================
   public topbar (2026-09-08): the studio is linked from the site nav now,
   so the title is a real h1, the monogram alone is the home link, and a
   small nav pairs "All tools" with the cross-link to the other tool.
   ===================================================================== */
.brand-home { display: inline-flex; flex: none; line-height: 0; border-radius: 12px; }
.brand-home:focus-visible { outline: 2px solid var(--purple-l); outline-offset: 3px; }
.brand .title h1 {
  font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 18px; line-height: 1.1;
  margin: 0; letter-spacing: -0.01em; color: var(--tx);
}
.topbar-nav { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.topbar-nav .btn { white-space: nowrap; }
.btn.topbar-link { background: transparent; border-color: transparent; color: var(--tx-dim); }
.btn.topbar-link:hover { color: var(--tx); border-color: var(--line-2); text-decoration: none; }
.footer-note a { color: var(--tx-dim); text-decoration: underline; text-underline-offset: 2px; }
.footer-note a:hover { color: var(--purple-xl); }
@media (max-width: 480px) {
  /* show bar: drop the SHOW caption so the show name stops truncating to "My …" beside New show */
  .show-bar-lbl { display: none; }
  .show-switch-wrap { flex: 1; min-width: 0; }
  .show-bar-inner > span:not([class]) { display: none; } /* the flex spacer: it would split the room 50/50 with the switch */
  .show-switch { width: 100%; max-width: none; }
  .show-switch b { flex: 1; min-width: 0; text-align: left; }
  .topbar { gap: 12px; }
  .topbar .spacer { display: none; }
  /* Not two full-width blocks. These are cross-links OUT of the tool, and stretching them
     made the loudest pair of controls on a phone's first screen a piece of navigation. */
  .topbar-nav { width: 100%; justify-content: flex-start; gap: 6px; }
  .topbar-nav .btn { flex: none; font-size: 12.5px; padding: 7px 11px; }
  /* the ghost "All tools" link floats beside a real button at this width; give both the same pill */
  .topbar-nav .btn.topbar-link { background: var(--el); border-color: var(--line-2); color: var(--tx); }

  /* export actions: three bordered clusters wrap raggedly at phone width (a 14px indent on the
     second row only, singletons on their own line). One 2-up grid instead: PDF full width on top,
     then pairs by intent (CSV/Print, Share/Console file, Save/Load) and Clear alone at the bottom. */
  .actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; align-items: stretch; }
  .act-group { display: contents; }
  .actions > span:not([class]) { display: none; } /* the flex spacer */
  .actions .btn { justify-content: center; min-height: 44px; }
  .actions .btn.primary { grid-column: 1 / -1; }
  .actions .btn.hire { grid-column: 1 / -1; order: -1; }
  .act-group:nth-child(2) .btn { order: 1; }
  .actions .btn.ghost { order: 2; grid-column: 1 / -1; }
  /* the export modal's own banner carries the beta warning; the badge is what wrapped "Console file" onto two lines here */
  .actions .exp-beta { display: none; }
  .actions .btn { padding-left: 8px; padding-right: 8px; gap: 7px; white-space: nowrap; }

  /* dip bank: at 42px a switch, a 9-bank was 454px wide and scrolled sideways with no cue, so switches
     7 to 9 were simply off screen. Divide the width evenly instead; a 10-bank still fits at 360. */
  .bank-stage { padding: 16px 6px 8px; }
  .bank-stage .dipbank { display: flex; width: 100%; margin: 0; gap: 2px; padding: 12px 5px 8px; }
  .dipsw { flex: 1 1 0; width: auto; min-width: 0; gap: 4px; }
  .dip-track { width: 18px; height: 64px; }
  .dip-on { font-size: 9px; letter-spacing: .04em; }
  .dip-wt { font-size: 10px; }
}
@media (max-width: 340px) {
  /* 320 px phones: the fixture count badge is what truncates the show name to "My …"; the count is in the stats card anyway */
  .show-switch-meta { display: none; }
  /* position head: the delete button wrapped onto its own line under Auto / arrows / copy */
  .pos-head-inner { gap: 6px; }
  .pin-ctl { gap: 3px; }
}

/* Provenance in the fixture search (2026-09-08): every group and row says where its chart
   came from, so a community chart from the Open Fixture Library is never mistaken for a
   Krank'd verified one. The PWA banners reuse the restore-banner look. */
.combo-group .co-src { float: right; font-weight: 600; letter-spacing: .04em; text-transform: none; color: var(--tx-faint); }
.combo-group .co-src.community { color: #d7b56d; }
.fleet-chip.community { color: #e6c98a; background: rgba(215, 181, 109, .14); border-color: rgba(215, 181, 109, .5); }
.src-note { display: block; width: 100%; margin-top: 6px; color: var(--tx-faint); }
main > .pwa-banner { margin: 0 0 14px; }
.pwa-banner .icon-btn { font-size: 18px; line-height: 1; }
/* install and update are purple (brand, an offer); offline is amber (a state, not an error) */
.pwa-banner.pwa-install, .pwa-banner.pwa-update { background: color-mix(in srgb, var(--purple-l) 12%, #0A0A0F);
  border-color: color-mix(in srgb, var(--purple-l) 45%, transparent); }
.pwa-banner.pwa-offline { background: var(--warn-bg); border-color: #5a4118; }
.pwa-banner.pwa-offline b { color: var(--warn); }

/* =====================================================================
   the fleet gallery (2026-09-11)
   The Krank'd tab of the fixture library, rendered by app/dmx/fleet.js.

   Every product photo in this catalogue is an alpha cutout on a dark tile, so the fixture
   itself can be the card: it stands in a pool of house purple rather than sitting inside a
   box, the way gear looks on a loading dock under a wash. That pool is the only decoration
   in here and the only thing that moves; everything else (identity, spec plate, channel
   modes) is quiet and left-aligned so a grid of 59 reads as one fleet, not 59 adverts.
   ===================================================================== */
.lib-modal.fleet-mode .lib-panel { width: min(1200px, 100%); }

/* rail: categories, then the two questions worth filtering on */
.fl-rail-head { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--tx-dim); padding: 12px 10px 5px; }
.fl-rail-head:first-child { padding-top: 4px; }
.fl-toggle { appearance: none; cursor: pointer; font: inherit; font-size: 13px; text-align: left;
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px; border-radius: 8px;
  border: 1px solid transparent; background: transparent; color: var(--tx-dim); transition: color .14s, background .14s, border-color .14s; }
.fl-toggle .ic { flex: none; opacity: .75; }
.fl-toggle > span:nth-of-type(1) { flex: 1; }
.fl-toggle:hover { background: var(--el); color: var(--tx); }
.fl-toggle.on { background: rgba(155, 77, 255, .14); border-color: color-mix(in srgb, var(--purple-l) 45%, transparent); color: #fff; font-weight: 600; }
.fl-toggle.on .ic { opacity: 1; color: var(--purple-xl); }

/* grid */
.fl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(208px, 1fr)); gap: 14px; }
/* equal-height rows: the plate is pushed to the foot of whichever card is tallest, so a grid
   of 59 reads as one shelf rather than a ragged stack */
.fl-card { position: relative; display: flex; flex-direction: column; height: 100%; overflow: hidden;
  background: linear-gradient(180deg, var(--card-2) 0%, var(--card) 62%);
  border: 1px solid var(--line); border-radius: 16px; }

/* the upper region is one big target: photo, identity, blurb, plate */
.fl-open { appearance: none; font: inherit; color: inherit; text-align: left; cursor: pointer; flex: 1;
  display: flex; flex-direction: column; gap: 7px; padding: 12px 13px 11px; background: none; border: 0; }
.fl-open:focus-visible { outline: 2px solid var(--purple-l); outline-offset: -3px; border-radius: 15px; }

.fl-shot { position: relative; display: block; aspect-ratio: 4 / 3; margin-bottom: 2px; }
.fl-shot img { position: relative; z-index: 1; display: block; width: 100%; height: 100%; object-fit: contain; }
/* the pool: an ellipse of purple under the fixture, blurred, brightening on approach */
.fl-pool { position: absolute; left: 6%; right: 6%; bottom: 2%; height: 46%; border-radius: 50%;
  background: radial-gradient(ellipse at 50% 100%, rgba(155, 77, 255, .40), rgba(125, 40, 219, .12) 55%, transparent 72%);
  filter: blur(9px); opacity: .75; transition: opacity .2s ease, transform .2s ease; }
.fl-card:hover .fl-pool, .fl-open:focus-visible .fl-pool { opacity: 1; transform: scale(1.06); }
.fl-card:hover { border-color: var(--line-2); }
.fl-noshot { display: grid; place-items: center; width: 100%; height: 100%; color: var(--tx-faint); }

/* the weatherproof rating, on the tile instead of at the bottom of a spec sheet */
.fl-ip { position: absolute; top: 10px; right: 11px; z-index: 2; font-size: 10.5px; font-weight: 700;
  letter-spacing: .04em; padding: 3px 7px; border-radius: 6px; color: #bfe3ff;
  background: rgba(26, 62, 92, .72); border: 1px solid rgba(120, 190, 240, .42); backdrop-filter: blur(2px); }

.fl-id { display: flex; flex-direction: column; gap: 1px; }
.fl-brand { font-size: 10px; font-weight: 700; letter-spacing: .11em; text-transform: uppercase; color: var(--purple-xl); opacity: .85; }
.fl-model { font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 14px; line-height: 1.25; }
.fl-blurb { font-size: 11.8px; line-height: 1.42; color: var(--tx-dim);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* spec plate: the three figures a tech checks before hanging one */
/* Flexed, not three equal columns: "3.6\u00b0\u201353.4\u00b0" needs more room than "26.5 kg" and a
   figure clipped to "3.6\u00b0\u20135..." is worth less than no figure at all. */
.fl-plate { display: flex; justify-content: space-between; margin-top: auto; padding-top: 9px;
  border-top: 1px solid var(--line); }
.fl-cell { display: flex; flex-direction: column; gap: 1px; min-width: 0; padding-right: 7px; }
/* The plate stretches to the tallest cell so a wrapped figure never shortens its neighbours,
   and .fl-card keeps height: 100% so the grid row stays flush. */
.fl-cell + .fl-cell { border-left: 1px solid var(--line); padding-left: 8px; }
.fl-cell:last-child { padding-right: 0; }
.fl-cell b { font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums;
  line-height: 1.25; overflow-wrap: anywhere; }
.fl-cell small { font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--tx-faint); }

/* footer: the channel modes, or the honest alternative */
.fl-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 0 13px 12px; }
.fl-foot .lib-mode { padding: 5px 9px; }
.fl-foot .lib-mode.fl-ch b { font-size: 12px; max-width: none; font-variant-numeric: tabular-nums; }
.fl-more { appearance: none; cursor: pointer; font: inherit; font-size: 11.5px; font-weight: 600;
  padding: 6px 9px; border-radius: 8px; border: 1px dashed var(--line-2); background: transparent;
  color: var(--tx-dim); transition: color .14s, border-color .14s; }
.fl-more:hover { color: var(--purple-xl); border-color: var(--purple-l); }
.fl-nochart { flex: 1; font-size: 11px; color: var(--tx-faint); }

/* loading skeleton: the card's own shape, so the grid does not jump when the photos land */
.fl-card.skel { height: 268px; border-style: dashed; animation: fl-breathe 1.5s ease-in-out infinite; }
@keyframes fl-breathe { 0%, 100% { opacity: .4; } 50% { opacity: .7; } }

/* ---- one fixture, in full ---- */
.fl-back { appearance: none; cursor: pointer; font: inherit; font-size: 13px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 7px; padding: 7px 11px 7px 8px; margin-bottom: 16px;
  border-radius: 9px; border: 1px solid var(--line); background: var(--el); color: var(--tx-dim); }
.fl-back:hover { color: #fff; border-color: var(--line-2); }
.fl-detail-grid { display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr); gap: 26px; align-items: start; }
.fl-detail-shot { position: sticky; top: 0; padding: 0 6px; }
.fl-shot.big { aspect-ratio: 1 / 1; }
.fl-shot.big .fl-pool { height: 40%; filter: blur(16px); }
.fl-detail-body > h3 { margin: 2px 0 10px; font-size: 23px; font-weight: 700; letter-spacing: -0.015em; }
.fl-lede { margin: 0 0 16px; font-size: 14px; line-height: 1.55; color: var(--tx-dim); max-width: 62ch; }
.fl-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.fl-tag { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600;
  padding: 4px 9px; border-radius: 999px; background: var(--el); border: 1px solid var(--line-2); color: var(--tx-dim); }
.fl-tag.ip { color: #bfe3ff; border-color: rgba(120, 190, 240, .42); background: rgba(26, 62, 92, .5); }
.fl-tag.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); background: var(--ok-bg); }
.fl-modes { margin-bottom: 18px; }
.fl-modes .lbl { display: block; margin-bottom: 3px; }
.fl-mode-hint { display: block; margin-bottom: 9px; }
.fl-mode-wrap { display: flex; flex-wrap: wrap; gap: 7px; }
.fl-hire { display: inline-flex; margin-bottom: 22px; }
.fl-custom { margin-bottom: 20px; padding: 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); }
.fl-nochart-note { margin: 0 0 12px; font-size: 13px; color: var(--tx-dim); }
.fl-custom-row .lbl { display: block; margin-bottom: 7px; }
.fl-custom input.ch-in { width: 78px; }

.fl-spec-tables { display: flex; flex-direction: column; gap: 18px; border-top: 1px solid var(--line); padding-top: 18px; }
.fl-spec-group h5 { margin: 0 0 8px; font-family: 'Poppins', sans-serif; font-size: 11px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--tx-faint); }
.fl-specs { display: grid; grid-template-columns: minmax(120px, 34%) 1fr; gap: 1px 18px; margin: 0; font-size: 13px; }
.fl-specs dt { padding: 6px 0; color: var(--tx-dim); }
.fl-specs dd { padding: 6px 0; margin: 0; border-bottom: 1px solid var(--line); }
.fl-specs dt { border-bottom: 1px solid var(--line); }

/* ---- the way in, from the Add card ---- */
/* The gallery button sits ON the Fixture label row. It used to sit under the search box,
   below the fold of an open dropdown, which made browsing something you had to already know
   about. */
.lbl-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 7px; }
.lbl-row .lbl { margin-bottom: 0; }
.fleet-btn { appearance: none; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 8px;
  color: var(--purple-xl); background: rgba(155, 77, 255, .12);
  border: 1px solid color-mix(in srgb, var(--purple-l) 42%, transparent); transition: background .14s, color .14s; }
.fleet-btn:hover { background: rgba(155, 77, 255, .22); color: #fff; }
.fleet-btn .ic { opacity: .9; }
/* and again as the first row of the dropdown, for anyone who opened the search first */
.combo-opt.browse.lead { border-bottom: 1px solid var(--line); margin-bottom: 4px; padding-bottom: 10px; }
.combo-opt.browse.lead .co-name { color: var(--purple-xl); }

@media (prefers-reduced-motion: reduce) {
  .fl-pool, .fl-card.skel { transition: none; animation: none; }
  .fl-card:hover .fl-pool { transform: none; }
}

@media (max-width: 900px) {
  .fl-detail-grid { grid-template-columns: 1fr; gap: 18px; }
  .fl-detail-shot { position: static; max-width: 280px; }
}

@media (max-width: 720px) {
  .fl-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  /* The rail is a horizontal scroller on a phone, so the two filters lead: at the end of
     eleven categories they would be a swipe nobody takes. */
  .lib-brands .fl-rail-head { padding: 0 4px; align-self: center; white-space: nowrap; }
  .lib-brands .fl-rail-head:not(.filt) { display: none; }
  .lib-brands .fl-rail-head.filt { order: -2; }
  .fl-toggle { width: auto; flex: none; min-height: 42px; order: -1; }
  .fl-blurb { -webkit-line-clamp: 3; }
  /* Three columns cannot hold "28,000 lm" on a 150px card, and a truncated figure is worse
     than no figure, so on a phone the plate stacks one figure per row. The labels stay:
     "kg" and "W" carry their own meaning but a bare "3.6-53.4" does not, and hiding the
     word BEAM to save 34px turns a spec into a riddle. */
  .fl-plate { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 3px 11px; }
  .fl-cell, .fl-cell:last-child { flex: 0 0 100%; flex-direction: row; align-items: baseline;
    justify-content: space-between; gap: 8px; padding: 0; }
  .fl-cell + .fl-cell { border-left: 0; padding-left: 0; }
  .fl-cell small { flex: none; }
  .fl-cell b { font-size: 11.5px; overflow: visible; text-align: right; }
  .fl-detail-body > h3 { font-size: 19px; }
  .fl-specs { grid-template-columns: 1fr; gap: 0; }
  .fl-specs dt { border-bottom: 0; padding-bottom: 0; font-size: 11px; letter-spacing: .04em; text-transform: uppercase; }
  .fl-specs dd { padding-top: 2px; }
}

/* =====================================================================
   ACCOUNTS: the optional "keep your shows" dialog and its two entry points
   The panel borrows the library modal's shell but sizes itself to a form:
   a full-height console panel around three fields would read as a bigger
   commitment than signing in actually is.
   ===================================================================== */
.lib-modal.acct-mode { z-index: 260; }
.acct-panel { width: min(460px, 100%); height: auto; max-height: min(88vh, 720px); }
.acct-body { padding: 18px; overflow-y: auto; }
.acct-pane { display: flex; flex-direction: column; gap: 14px; }
.acct-lead { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--tx-dim); }
.acct-lead b { color: var(--tx); font-weight: 600; }
.acct-field { display: flex; flex-direction: column; gap: 7px; }
.acct-field > span { font-size: 11px; font-weight: 600; color: var(--tx-faint); text-transform: uppercase; letter-spacing: .06em; }
input.acct-input { width: 100%; font-size: 15px; padding: 12px 14px; }
/* The code is the one moment the dialog asks for precision, so it is the one element that
   is allowed to be loud: tabular, wide-tracked, big enough to check against a phone
   notification without squinting on a dark stage. */
input.acct-code { font-family: 'Poppins', sans-serif; font-size: 26px; font-weight: 700; letter-spacing: .34em;
  text-align: center; padding: 14px 10px 14px 20px; font-variant-numeric: tabular-nums; color: var(--purple-xl); }
input.acct-code::placeholder { color: var(--line-2); letter-spacing: .34em; }
.acct-go { width: 100%; justify-content: center; padding: 12px; font-size: 14px; }
.acct-fine { margin: 0; line-height: 1.5; }
.acct-alt { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.acct-note { display: flex; align-items: flex-start; gap: 9px; margin-top: 14px; padding: 11px 13px; border-radius: var(--radius-sm);
  font-size: 13px; line-height: 1.5; background: var(--bad-bg); border: 1px solid #4a1a20; color: var(--bad); }
.acct-note.ok { background: var(--ok-bg); border-color: #1c4a30; color: var(--ok); }
.acct-note .ic { flex: none; margin-top: 1px; }
.acct-who { display: flex; align-items: center; gap: 12px; }
.acct-who .ic { color: var(--ok); flex: none; }
.acct-who b { display: block; font-family: 'Poppins', sans-serif; font-size: 15px; }
.acct-who span { display: block; margin-top: 2px; word-break: break-all; }
.acct-acts { display: flex; gap: 8px; flex-wrap: wrap; }
.acct-danger { margin-top: 6px; padding-top: 14px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 10px; }
.acct-danger p { margin: 0; color: var(--tx-faint); line-height: 1.5; }
.btn.sm.danger { color: var(--bad); border-color: #4a1a20; }
.btn.sm.danger:hover { background: var(--bad-bg); border-color: var(--bad); }

/* entry point 1: the foot of the show menu */
.show-menu-acct { padding: 7px; border-top: 1px solid var(--line); background: var(--card); }
.acct-row { width: 100%; justify-content: flex-start; align-items: center; text-align: left; padding: 9px 11px; }
.acct-row > .ic { flex: none; }
.acct-row.on > .ic { color: var(--ok); }
.acct-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.acct-txt b { font-weight: 600; }
.acct-row .acct-mini { font-weight: 500; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* entry point 2: a quiet mark on the switcher, so "it is saved" needs no dialog to read */
.acct-mark { display: inline-flex; color: var(--ok); }

@media (max-width: 560px) {
  .acct-panel { width: 100%; height: 100%; max-height: none; border-radius: 0; border: 0; }
}
.acct-fine a { color: var(--purple-xl); text-decoration: underline; text-underline-offset: 2px; }
/* Deletion is available, not advertised: it sits at its own width at the foot of the panel
   rather than stretching across it like a primary action. */
.acct-del { align-self: flex-start; }
