/* MONO / CHAIN ────────────────────────────────────────────────────────────────────────────
   Page-local layer for mono.html ONLY. Loaded after:
     desktop-tokens.css  (legacy --bg/--text/--card ladder, still referenced by inline styles)
     signal.css          (the .sig-scale tick ruler that js/signal/enhance.js builds)
     chain.css           (the CHAIN design system — every value below is one of its --cn-* tokens)

   Rules of this file:
   · No invented colours, sizes, radii or motion values. Everything resolves to a --cn-* token
     from chain.css. The two exceptions are documented inline (rgba() spellings of --cn-amber
     that need an alpha channel, and the per-module tint mix() endpoints, both of which are
     literally chain.css's own values).
   · Mono keeps its safelight identity: the accent is amber, never Studio's chartreuse. Chain's
     own --cn-amber IS that amber (#E8863A vs the old #E8743C), so "keep mono's identity" and
     "use Chain's tokens" turn out to be the same instruction.
   · The engine is untouched. Every rule here dresses chrome that already existed.
   ────────────────────────────────────────────────────────────────────────────────────────── */

/* The reset that used to sit at the top of mono.html's inline <style>. chain.css supplies
   box-sizing for html.cn-app but not the margin/padding zeroing this page's markup assumes. */
*,*::before,*::after{ box-sizing:border-box; margin:0; padding:0; }

:root{
  /* ── the safelight, re-pointed at Chain's amber ─────────────────────────────────────── */
  --safe:      var(--cn-amber);
  --safe-hi:   var(--cn-amber-hi);
  /* rgba() spellings of --cn-amber (232,134,58) — needed because these two are used as fills
     and borders that must carry their own alpha, which var() cannot add. */
  --safe-dim:  rgba(232,134,58,0.16);
  --safe-line: rgba(232,134,58,0.40);
  /* signal.css reads this for every ruler flag, ramp selection and focus rule. */
  --sig-accent: var(--cn-amber);

  /* ── type: one family, Chain's self-hosted Urbanist. The old Inter / JetBrains Mono pair
     came from a fonts.googleapis.com <link> that is blocked in this app (COOP/COEP + the LOCAL
     status pill), so it was never actually loading — both vars fell back to system faces. ── */
  --font-sans:  var(--cn-font);
  --font-serif: var(--cn-font);

  /* ── legacy desktop-tokens ladder, aliased onto Chain so the inline style="" attributes
     still in mono.html's markup and template strings resolve to Chain values. ───────────── */
  --bg:            var(--cn-page);
  --surface:       transparent;
  --card:          var(--cn-surf);
  --card-2:        var(--cn-surf-off);
  --border:        var(--cn-line);
  --border-strong: var(--cn-line-chip);
  --text:          var(--cn-ink);
  --text-2:        var(--cn-t-60);
  --text-3:        var(--cn-t-40);
  --r:             var(--cn-r-10);
}

/* Every number on this page is a reading. */
.row-num, .cn-hero-val b, .zoneleg, .panel-category-count,
.cn-stage-num, .cn-stage-count, .cn-mod-step, .spot, #dims{
  font-variant-numeric: tabular-nums;
}

/* ══ SHELL ═══════════════════════════════════════════════════════════════════════════════
   .cn-shell / .cn-bar / .cn-body / .cn-rail / .cn-left / .cn-right all come from chain.css
   unchanged. Only mono-specific additions live here. */

.cn-wordmark{ color:var(--cn-ink); text-decoration:none; display:flex; align-items:center; }
.cn-wordmark:hover{ color:var(--cn-ink); }

/* Room tag — the darkroom's own badge, in the bar where Studio has none. */
.mono-roomtag{
  flex:none; height:20px; display:flex; align-items:center; padding:0 9px;
  border-radius:var(--cn-r-pill); border:1px solid var(--safe-line); color:var(--cn-amber);
  font-size:var(--cn-fs-8); letter-spacing:var(--cn-ls-24);
}

/* Command-bar buttons: mono's press-state is a class (`.on`) set by the existing pointer
   handlers, so it needs the same treatment chain.css gives [aria-pressed="true"]. */
.cn-cmdbtn.on{ background:var(--cn-hov-14); }
.cn-cmdbtn.on span{ color:var(--cn-amber); }
.cn-cmdbtn.on svg{ stroke:var(--cn-amber); }

/* Export format — a <select> that has to read like one of the bar's own micro-labels. */
.mono-barsel{ position:relative; display:flex; align-items:center; flex:none; }
.mono-barsel select{
  appearance:none; -webkit-appearance:none; font-family:inherit;
  font-size:var(--cn-fs-85); letter-spacing:var(--cn-ls-14); color:var(--cn-t-70);
  height:24px; padding:0 22px 0 10px; border-radius:var(--cn-r-pill); cursor:pointer;
  background:var(--cn-hov-08); border:1px solid var(--cn-line-btn);
}
.mono-barsel select:hover{ background:var(--cn-hov-16); color:var(--cn-ink); }
.mono-barsel svg{
  position:absolute; right:8px; width:9px; height:9px; pointer-events:none;
  fill:none; stroke:var(--cn-t-50); stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round;
}

/* ══ RAIL ════════════════════════════════════════════════════════════════════════════════
   Four tiles, one per control group, carrying the same grey→amber walk down the chain that
   chain.css's --wash/--fill/--tint contract expects (set per-tile inline in the markup).
   These are disclosure toggles, not tabs, so the state is aria-expanded — which means
   repeating chain.css's [aria-selected="true"] block against the correct attribute. */
.cn-stage[aria-expanded="true"]{ background:var(--fill); border-color:var(--tint); }
.cn-stage[aria-expanded="true"] .cn-stage-title,
.cn-stage[aria-expanded="true"] .cn-stage-num,
.cn-stage[aria-expanded="true"] .cn-stage-count{ color:var(--cn-ink-on-amber); }
.cn-stage:hover{ border-color:var(--tint); }

/* ══ LEFT COLUMN ═════════════════════════════════════════════════════════════════════════ */
.cn-left{ overflow:hidden; }

/* the always-on instrument: paper grade + stock + the live histogram, above the module list
   exactly where Chain's own .cn-histostrip sits. */
.mono-hero{ flex:none; }
.mono-hero .cn-hero-cap{ margin-top:5px; }
.mono-scope{
  margin-top:11px; border-radius:var(--cn-r-12); padding:8px 8px 6px;
  background:var(--cn-surf-off); border:1px solid var(--cn-line);
}
#histo{ display:block; width:100%; height:74px; border-radius:2px; }
.zoneleg{
  display:flex; justify-content:space-between; margin-top:5px;
  font-size:var(--cn-fs-8); letter-spacing:var(--cn-ls-10); color:var(--cn-t-40);
}
.mono-hero .cn-note{ margin-top:9px; }

/* module list — chain.css owns .cn-modlist; mono only needs the group wrappers inside it. */
.cn-modlist{ padding-bottom:2px; }

/* ── control group (Film & Tone / Toning & Paper / …) ── */
.panel-category{ flex:none; }
.panel-category + .panel-category{ margin-top:14px; }
.panel-category-header{ display:flex; align-items:center; gap:9px; padding:0 2px 7px; }
.panel-category-btn{
  background:none; border:0; padding:0; cursor:pointer; font-family:inherit;
  font-size:var(--cn-fs-9); letter-spacing:var(--cn-ls-20); text-transform:uppercase;
  color:var(--cn-t-55);
}
.panel-category-header:hover .panel-category-btn{ color:var(--cn-t-90); }
.panel-category-count{
  font-size:var(--cn-fs-8); letter-spacing:var(--cn-ls-10); color:var(--cn-t-40);
  background:none; border:0; border-radius:0; padding:0;
}
.panel-category-header .rule{ flex:1; height:1px; background:var(--cn-line-div); }
.panel-category-header .chevron{
  width:13px; height:13px; flex:none; fill:none; stroke:var(--cn-t-50); stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round;
  transition:transform var(--cn-t-state) var(--cn-ease);
}
.panel-category.open .panel-category-header .chevron{ transform:rotate(180deg); }
.panel-category-body{ display:none; }
.panel-category.open .panel-category-body{ display:block; }
.panel-category-body-inner{ display:flex; flex-direction:column; gap:var(--cn-mod-gap); }

/* ── module card — chain.css's .cn-mod, worn by mono's own .card ─────────────────────────
   Not renamed: `.card`, `.card.open`, `.card.dirty` and `.card-head` are all load-bearing in
   mono's own delegated click handler and dirty-flag pass. This is the same object in Chain
   dress, not a new one. */
.card{
  position:relative; flex:none; border-radius:var(--cn-r-15); overflow:hidden;
  background:var(--cn-surf-off); border:1px solid var(--cn-line-off); border-top:1px solid var(--cn-line-off);
  box-shadow:inset 0 0 0 999px var(--tint-wash-off, transparent);
  transition:box-shadow var(--cn-t-state) var(--cn-ease), border-color var(--cn-t-state) var(--cn-ease);
}
.card.open{
  background:var(--cn-surf); border-color:var(--cn-line);
  box-shadow:inset 0 0 0 999px var(--tint-wash-on, transparent);
}
.card .cn-mod-edge{ opacity:.55; }
.card.open .cn-mod-edge{ opacity:1; }
.card-head{
  display:flex; align-items:center; gap:11px; padding:10px 12px 10px 14px;
  cursor:pointer; user-select:none;
}
.card-head:hover{ background:var(--cn-hov-08); }
.card .cn-mod-step{ color:var(--tint, var(--cn-t-22)); opacity:.7; }
.card.open .cn-mod-step{ opacity:1; }
.card .cn-mod-title{ font-size:var(--cn-fs-13); color:var(--cn-t-45); }
.card.open .cn-mod-title{ color:var(--cn-ink); }
/* the dirty flag, in Chain's ON/OFF slot */
.card .cn-mod-state{ color:var(--cn-amber); opacity:0; transition:opacity var(--cn-t-state) var(--cn-ease); }
.card.dirty .cn-mod-state{ opacity:1; }
.card .cn-chev svg{ display:block; }
.card.open .cn-chev{ transform:rotate(180deg); }
.card-body{ display:none; padding:0 12px 13px 14px; }
.card.open .card-body{ display:block; }

/* ── foot ── */
.foot{
  flex:none; padding:11px 4px 2px; border-top:1px solid var(--cn-line-div);
  font-size:var(--cn-fs-85); letter-spacing:var(--cn-ls-14); line-height:1.7;
  color:var(--cn-t-40); text-align:center;
}

/* ══ CONTROLS ════════════════════════════════════════════════════════════════════════════ */

/* ── slider row → Chain's .cn-tool head + tick strip ────────────────────────────────────
   The strip itself is signal.css's .sig-scale, built around the real <input type=range> by
   js/signal/enhance.js. Retuning it to Chain's geometry (11px ticks, every 6th at 17px, an
   amber pennant, band running default→value) rather than replacing it keeps keyboard
   stepping, screen-reader semantics, double-click-to-default, tick magnetism and the visible
   detent — all of which a div-based strip would have thrown away. */
.row{ margin-top:11px; }
.row:first-child{ margin-top:9px; }
.row-top{ display:flex; align-items:center; gap:9px; margin:0; }
.row-top label{
  display:flex; align-items:center; gap:7px;
  flex:1; min-width:0; font-size:var(--cn-fs-12); color:var(--cn-t-90); cursor:default;
}
/* the ≈ grade readout that rides the Contrast row's label */
.row-hint{ font-size:var(--cn-fs-9); letter-spacing:var(--cn-ls-10); color:var(--cn-t-40); }
.row-ctl{ display:flex; align-items:center; gap:5px; flex:none; }
.row-ctl > span{ font-size:var(--cn-fs-95); letter-spacing:var(--cn-ls-10); color:var(--cn-t-50); }
.row-num{
  width:58px; text-align:right; padding:1px 4px; border-radius:var(--cn-r-5);
  font-family:inherit; font-size:var(--cn-fs-16); font-weight:var(--cn-w-thin);
  letter-spacing:var(--cn-ls-n2); color:var(--cn-ink);
  background:transparent; border:1px solid transparent;
  -moz-appearance:textfield; transition:border-color var(--cn-t-state) var(--cn-ease),
                                        background-color var(--cn-t-state) var(--cn-ease);
}
.row-num::-webkit-inner-spin-button,.row-num::-webkit-outer-spin-button{ -webkit-appearance:none; margin:0; }
.row:hover .row-num{ border-color:var(--cn-line-2); }
.row-num:focus{ outline:none; border-color:var(--cn-amber); background:var(--cn-hov-08); }
.row-reset{
  width:20px; height:20px; flex:none; display:flex; align-items:center; justify-content:center;
  border:0; background:none; border-radius:50%; cursor:pointer; color:var(--cn-t-55);
  opacity:0; transition:opacity var(--cn-t-state) var(--cn-ease),
                        background-color var(--cn-t-state) var(--cn-ease),
                        transform 0.25s var(--cn-ease);
}
.row:hover .row-reset, .row-reset:focus-visible{ opacity:1; }
.row-reset:hover{ background:var(--cn-surf-track); color:var(--cn-ink); transform:rotate(-40deg); }
.row-reset:hover:active{ transform:rotate(-40deg) scale(0.90); }
.row-reset svg{ width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.4;
                stroke-linecap:round; stroke-linejoin:round; }

/* the tick strip itself */
.sig-scale{ height:27px; margin-top:7px; }
.sig-scale-ticks{ inset:auto 0 0 0; height:19px; align-items:flex-end; }
/* HAIRLINES, NOT BLOCKS. al (with a screenshot of this exact ruler): "these mono sliders do not
   match the ones on studio." They didn't: this page used to re-ink every tick as a flex-grown
   block up to 6px wide, so where Studio draws a fine 1px ruler Mono drew a barcode. The width/
   flex/margin overrides are gone — signal.css's own `flex:0 0 1px; width:1px` hairline shows
   through, identical ink to Studio and Print. All Mono keeps is HEIGHT, scaled to its shorter
   19px rail (11 minor / 17 major / 21 centre / 19 mark vs signal.css's 16/23/27/30) so the ruler
   fits the compact cards without clipping — same instrument, sized to the room it's in. */
.sig-scale-ticks i{ height:11px; }
.sig-scale-ticks i.on{ height:11px; }
.sig-scale-ticks i.maj{ height:17px; }
.sig-scale-ticks i.mid{ height:21px; }
.sig-scale-ticks i.mark{ height:19px; }
.sig-scale-ticks::after{ bottom:0; background:var(--cn-line-off); }
.sig-scale:hover .sig-scale-ticks::after,
.sig-scale[data-live] .sig-scale-ticks::after{ background:var(--cn-line-2); }
.sig-scale:hover .sig-scale-ticks i{ height:12px; }
.sig-scale:hover .sig-scale-ticks i.on{ height:12px; }
.sig-scale:hover .sig-scale-ticks i.maj{ height:18px; }
.sig-scale:hover .sig-scale-ticks i.mid{ height:22px; }
.sig-scale:hover .sig-scale-ticks i.mark{ height:20px; }
/* magnetism — same mechanism, compact heights */
.sig-scale[data-live] .sig-scale-ticks i{ --sig-tick-h:11px; height:calc(var(--sig-tick-h) + var(--near,0) * 5px); }
.sig-scale[data-live] .sig-scale-ticks i.maj{ --sig-tick-h:17px; }
.sig-scale[data-live] .sig-scale-ticks i.mid{ --sig-tick-h:21px; }
.sig-scale[data-live] .sig-scale-ticks i.mark{ --sig-tick-h:19px; }

/* ── section labels ── */
.field-label, .subhead{
  display:flex; align-items:center; gap:9px; margin:16px 0 0;
  font-size:var(--cn-fs-85); letter-spacing:var(--cn-ls-24); text-transform:uppercase;
  color:var(--cn-t-55);
}
.field-label:first-child, .subhead:first-child{ margin-top:11px; }
.subhead::after{ content:''; flex:1; height:1px; background:var(--cn-line-div); }
.field-label span, .subhead span{ text-transform:none; letter-spacing:var(--cn-ls-06); color:var(--cn-t-40); }

/* ── notes ── */
.card-note, .curve-hint, .stock-note{
  font-size:var(--cn-fs-105); line-height:1.45; color:var(--cn-t-50);
}
.card-note{ margin:2px 0 11px; }
.curve-hint{ margin-top:8px; }
.stock-note{ margin-top:9px; padding-left:10px; border-left:1px solid var(--cn-line-2); }
.stock-note:empty{ display:none; }

/* ── selects → Chain's .cn-picker box ── */
.sel{
  width:100%; height:40px; padding:0 32px 0 13px; border-radius:var(--cn-r-13); cursor:pointer;
  appearance:none; -webkit-appearance:none; font-family:inherit; font-size:var(--cn-fs-12);
  color:var(--cn-ink); background-color:rgba(238,242,241,0.045); border:1px solid var(--cn-line);
  background-repeat:no-repeat; background-position:right 12px center;
  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='%23EEF2F1' stroke-opacity='0.5' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  transition:border-color var(--cn-t-state) var(--cn-ease);
}
.sel:hover{ border-color:var(--cn-line-btn); }
.sel:focus{ outline:none; border-color:var(--cn-amber); }
.sel.hero{ font-size:var(--cn-fs-125); }

/* ── chips → Chain's .cn-chip pill ─────────────────────────────────────────────────────
   Judgment call: chain.css fills a selected chip with --cn-ink (near-white). In a darkroom
   that is the brightest object on the screen for a control that is merely "which filter".
   The selected state here is the amber fill chain.css already uses for .cn-cta and
   .cn-checkbox — same token pair (--cn-amber / --cn-ink-on-amber), safelight-safe. */
.btns{ display:flex; flex-wrap:wrap; gap:5px; margin-top:8px; }
.chip{
  flex:0 1 auto; min-width:0; padding:6px 12px; border-radius:var(--cn-r-pill); cursor:pointer;
  text-align:center; white-space:nowrap; font-family:inherit;
  font-size:var(--cn-fs-10); letter-spacing:var(--cn-ls-06);
  background:transparent; border:1px solid var(--cn-line-chip); color:var(--cn-t-60);
  transition:transform var(--cn-t-state) var(--cn-ease), filter var(--cn-t-state) var(--cn-ease),
             background-color var(--cn-t-state) var(--cn-ease), border-color var(--cn-t-state) var(--cn-ease),
             color var(--cn-t-state) var(--cn-ease);
}
.chip:hover{ border-color:var(--cn-line-check); color:var(--cn-ink); }
.chip:active{ transform:scale(0.94); filter:brightness(0.90); }
.chip.on{ background:var(--cn-amber); border-color:transparent; color:var(--cn-ink-on-amber); }
.chip small{ display:block; font-size:var(--cn-fs-7); letter-spacing:var(--cn-ls-10);
             color:var(--cn-t-40); margin-top:2px; }
.chip.on small{ color:rgba(26,13,3,0.7); }

/* ── buttons → Chain's .cn-action ── */
.mini{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  min-height:32px; padding:0 12px; border-radius:var(--cn-r-12); cursor:pointer;
  font-family:inherit; font-size:var(--cn-fs-11); font-weight:var(--cn-w-thin);
  white-space:nowrap; background:transparent; border:1px solid var(--cn-line-2);
  color:var(--cn-t-60);
  transition:transform var(--cn-t-state) var(--cn-ease), filter var(--cn-t-state) var(--cn-ease),
             background-color var(--cn-t-state) var(--cn-ease), border-color var(--cn-t-state) var(--cn-ease),
             color var(--cn-t-state) var(--cn-ease);
}
.mini:hover{ border-color:var(--cn-line-btn); color:var(--cn-ink); }
.mini:active{ transform:scale(0.94); filter:brightness(0.90); }
.mini svg{ width:12px; height:12px; flex:none; }
.mini.on{ background:var(--cn-amber); border-color:transparent; color:var(--cn-ink-on-amber); }
.mini:disabled{ opacity:var(--cn-disabled-alpha); cursor:default; }
.mini:disabled:hover{ border-color:var(--cn-line-2); color:var(--cn-t-60); }
.mini:disabled:active{ transform:none; filter:none; }

.dz-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  min-height:38px; padding:0 18px; border-radius:var(--cn-r-12); cursor:pointer;
  font-family:inherit; font-size:var(--cn-fs-12); text-decoration:none;
  background:var(--cn-amber); border:1px solid transparent; color:var(--cn-ink-on-amber);
  transition:transform var(--cn-t-state) var(--cn-ease), filter var(--cn-t-state) var(--cn-ease),
             background-color var(--cn-t-state) var(--cn-ease), border-color var(--cn-t-state) var(--cn-ease);
}
.dz-btn:hover{ background:var(--cn-amber-hi); }
.dz-btn:active{ transform:scale(0.94); filter:brightness(0.90); }
.dz-btn.ghost{ background:var(--cn-surf-btn); border-color:var(--cn-line-btn); color:var(--cn-ink); }
.dz-btn.ghost:hover{ background:var(--cn-hov-18); }

/* ── tone curve ── */
#curve{
  display:block; width:100%; height:200px; cursor:crosshair; touch-action:none;
  border-radius:var(--cn-r-12); background:var(--cn-surf-off); border:1px solid var(--cn-line);
}

/* ── light-leak overlay picker → Chain's .cn-dirt-tile grid ── */
.ov-grid{ display:grid; grid-template-columns:repeat(5,1fr); gap:6px; margin:9px 0 0; }
.ov-thumb{
  position:relative; aspect-ratio:1/1; padding:0; overflow:hidden; cursor:pointer;
  border-radius:var(--cn-r-9); background:var(--cn-surf-off); border:1px solid var(--cn-line);
  transition:border-color var(--cn-t-state) var(--cn-ease), box-shadow var(--cn-t-state) var(--cn-ease);
}
.ov-thumb:hover{ border-color:var(--cn-line-chip); }
.ov-thumb.on{ border-color:var(--cn-amber); box-shadow:0 0 0 1px var(--cn-amber); }
.ov-thumb img{ width:100%; height:100%; object-fit:cover; display:block; filter:grayscale(1) contrast(1.05); }
.ov-place{ margin-top:16px; padding-top:12px; border-top:1px solid var(--cn-line-div); }
.ov-btn-row{ display:flex; gap:6px; margin-top:10px; }
.ov-btn-row .mini{ flex:1; }
/* draggable ⊕ placement marker over the canvas */
.ov-marker{
  position:absolute; width:34px; height:34px; margin:-17px 0 0 -17px; z-index:6;
  color:var(--cn-amber); cursor:grab; display:none; touch-action:none;
  filter:drop-shadow(0 0 3px rgba(0,0,0,.85));
}
.ov-marker.show{ display:block; }
.ov-marker:active{ cursor:grabbing; }
.ov-marker svg{ width:100%; height:100%; }

/* ══ RIGHT COLUMN ════════════════════════════════════════════════════════════════════════ */
.mono-vtools-hint{ font-size:var(--cn-fs-95); letter-spacing:var(--cn-ls-10); color:var(--cn-t-45); }

.canvas-wrap{
  display:flex; align-items:center; justify-content:center; padding:20px; min-height:0;
}
#view{
  max-width:100%; max-height:100%; object-fit:contain; display:none; cursor:crosshair;
  border-radius:var(--cn-r-5); box-shadow:0 20px 60px rgba(0,0,0,.6); image-rendering:auto;
}

.dropzone{
  position:absolute; inset:18px; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:16px; padding:24px; text-align:center;
  border:1px dashed var(--cn-line-chip); border-radius:var(--cn-r-16);
  color:var(--cn-t-60); transition:border-color var(--cn-t-state) var(--cn-ease),
                                   background-color var(--cn-t-state) var(--cn-ease);
}
.dropzone.hide{ display:none; }
.dropzone.drag{ border-color:var(--cn-amber); background:var(--safe-dim); color:var(--cn-ink); }
.dropzone h2{ font-size:var(--cn-fs-16); font-weight:var(--cn-w-reg);
              letter-spacing:var(--cn-ls-n2); color:var(--cn-ink); }
.dropzone p{ font-size:var(--cn-fs-12); line-height:1.5; max-width:360px; margin-top:6px; }
.dz-icon{ width:34px; height:34px; color:var(--cn-t-30); }
.recent{ display:flex; gap:8px; flex-wrap:wrap; justify-content:center; max-width:420px; }
.recent img{
  width:54px; height:54px; object-fit:cover; cursor:pointer;
  border-radius:var(--cn-r-8); border:1px solid var(--cn-line); filter:grayscale(1) contrast(1.05);
  transition:border-color var(--cn-t-state) var(--cn-ease), transform var(--cn-t-state) var(--cn-ease);
}
.recent img:hover{ border-color:var(--cn-amber); transform:translateY(-2px); }
.recent-label{ font-size:var(--cn-fs-85); letter-spacing:var(--cn-ls-22); color:var(--cn-t-40); }

/* spot meter — reads over the print, in Chain's EXIF-strip voice */
.spot{
  position:absolute; left:16px; bottom:14px; display:flex; align-items:center; gap:10px;
  height:var(--cn-exif-h); padding:0 13px; border-radius:var(--cn-r-14);
  background:color-mix(in srgb, var(--cn-well) 88%, transparent);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  border:1px solid var(--cn-line); pointer-events:none; opacity:0;
  font-size:var(--cn-fs-95); letter-spacing:var(--cn-ls-14); color:var(--cn-t-60);
  transition:opacity var(--cn-t-state) var(--cn-ease);
}
.spot.on{ opacity:1; }
.spot .sw{ width:16px; height:16px; border-radius:var(--cn-r-5); border:1px solid var(--cn-line-chip); }
.spot b{ color:var(--cn-ink); font-weight:var(--cn-w-reg); }

.busy{
  display:none; align-items:center; gap:8px; flex:none;
  font-size:var(--cn-fs-85); letter-spacing:var(--cn-ls-18); text-transform:uppercase;
  color:var(--cn-amber);
}
.busy.on{ display:flex; }
@keyframes spin{ to{ transform:rotate(360deg) } }
.spin{ width:11px; height:11px; border-radius:50%; border:2px solid currentColor;
       border-top-color:transparent; animation:spin .7s linear infinite; }

/* report panel */
.report-panel{ display:none; }
.report-panel.on{ display:block; }
.report-panel-top{ display:flex; align-items:center; gap:9px; }
.report-panel-head{ font-size:var(--cn-fs-85); letter-spacing:var(--cn-ls-24); color:var(--cn-t-55); }
.report-panel-top .rule{ flex:1; height:1px; background:var(--cn-line-div); }
.report-panel-x{
  width:24px; height:24px; flex:none; display:flex; align-items:center; justify-content:center;
  border:0; background:none; border-radius:var(--cn-r-7); cursor:pointer; color:var(--cn-t-50);
  transition:background-color var(--cn-t-state) var(--cn-ease), color var(--cn-t-state) var(--cn-ease);
}
.report-panel-x:hover{ background:var(--cn-hov-12); color:var(--cn-ink); }
.report-panel-x svg{ width:13px; height:13px; }
#reportText{
  width:100%; margin-top:9px; padding:9px 11px; resize:vertical;
  font-family:inherit; font-size:var(--cn-fs-12); line-height:1.6; color:var(--cn-ink);
  background:var(--cn-surf); border:1px solid var(--cn-line-2); border-radius:var(--cn-r-10);
}
#reportText:focus{ outline:none; border-color:var(--cn-amber); }
.report-actions{ display:flex; gap:8px; margin-top:9px; }

/* session filmstrip */
/* Mono's strip is now Chain's .cn-filmstrip-thumb, rendered by js/gallery/filmstrip.js — the
   same component Studio and the Print Room use. Everything this block used to declare (the 64x44
   cover-cropped box, the active border, the amber worked border+glow) lives in chain.css now, so
   the only thing left here is the row itself.

   The three comments this replaces were all the same story: al asking for Mono's strip to look
   like Studio's, and each fix being hand-copied across — the forced grayscale, then the
   near-invisible edited dot, then the QC sweep for the dot that the previous fix said it had
   removed and hadn't. Copies drift; there is one copy now. */
.mono-filmstrip{ gap:8px; overflow-x:auto; padding:2px 2px 0; }

.hidden-input{ position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }

/* ══ RESPONSIVE ══════════════════════════════════════════════════════════════════════════
   chain.css pins html/body to overflow:hidden and the shell to 100dvh — right for the desktop
   app frame, wrong for a phone. Below 900px the shell becomes a normal scrolling document and
   the rail lies down. The command bar never wraps: it scrolls inside itself, so the page never
   scrolls sideways. */
@media (max-width:1180px){
  .cn-bar{ gap:10px; padding:0 12px; }
  .mono-vtools-hint{ display:none; }
}
@media (max-width:900px){
  html.cn-app, html.cn-app body{ overflow:visible; height:auto; }
  .cn-shell{ height:auto; min-height:100dvh; overflow:visible; }
  .cn-bar{ overflow-x:auto; overflow-y:hidden; scrollbar-width:none; }
  .cn-bar::-webkit-scrollbar{ display:none; }
  .cn-bar > *{ flex:none; }
  .cn-bar .sp{ flex:1 0 8px; }
  .cn-body{ flex-direction:column; }
  .cn-rail{ flex-direction:row; width:auto; height:auto; flex:none; }
  .cn-stage{ flex:1 1 0; min-height:0; padding:9px 4px; gap:6px;
             flex-direction:row; justify-content:center; align-items:center; }
  .cn-stage-title{ writing-mode:horizontal-tb; transform:none; letter-spacing:var(--cn-ls-14);
                   font-size:var(--cn-fs-9); }
  .cn-stage-count{ display:none; }
  .cn-left{ width:auto; flex:none; overflow:visible; }
  .cn-modlist{ overflow:visible; flex:none; }
  .cn-right{ flex:none; }
  .cn-frame{ flex:none; height:min(64vh, 520px); }
}
@media (max-width:560px){
  .cn-wordmark{ font-size:var(--cn-fs-10); letter-spacing:var(--cn-ls-12); }
  .cn-nav{ gap:11px; }
  .ov-grid{ grid-template-columns:repeat(4,1fr); }
  .cn-frame{ height:min(56vh, 420px); }
  .canvas-wrap{ padding:12px; }
  .dropzone{ inset:10px; padding:16px; }
}
