/* CrunchyShader — the app's own CSS: its LAYOUT and its ACCENT. Linked with <link rel="stylesheet"> so it works on file://.
 *
 * The look itself (neutrals, buttons, sliders, checkboxes, the Library, suite, Settings, Feedback and desktop dialogs)
 * is crunchy-base.css, the suite's shared stylesheet (crunchyCore), linked FIRST; this file must not override its
 * FLOOR rules (square, the hard step, the neutrals, no blur, gradients or glows). Each app keeps its own accent
 * (CONSOLIDATION-PLAN.md §9): CrunchyShader is cyan, as its row in suite.js.
 *
 * --css-build is checked by index.html: bump both together whenever a feature needs new rules here.
 * The layout is CrunchyItems' (the suite's shape): one header row of globals, the generator row, the picture strip, then
 * the editor on the left and the preview on the right, the Library docked as a last column.
 */
:root {
  --css-build: 9;
  /* cyan, and the darker step under a filled button */
  --accent: #36d6e7;
  --accent-dk: #1b8a97;
  /* the preview's backdrops behind a sprite's clear pixels */
  --bd-dark: #2a2634;
  --bd-light: #c4c8ce;
}

* { box-sizing: border-box; }
button:disabled { opacity: .45; cursor: default; }
/* [hidden] loses to any author `display` rule without this (inherited from CrunchyVFX and CrunchyTile) */
[hidden] { display: none !important; }
html, body { height: 100%; }
body { margin: 0; display: flex; flex-direction: column; }

/* ---- the header: the app, then the globals in the suite's order ---- */
header { flex: none; display: flex; align-items: center; gap: 12px; padding: 8px 14px; background: var(--panel);
         border-bottom: 2px solid var(--drop); min-width: 0; }
header h1 { margin: 0; font-size: 17px; white-space: nowrap; }
/* THE WORDMARK: crunchyCore tools/make-wordmarks.mjs draws wordmark.png (1 px per art pixel); it is shown at exactly 2x,
   never stretched (the img's width/height are 2x its real size; the wiring test checks). Its 34 px is the header row's
   own content height (the buttons'), so the row keeps its height. The h1's text stays for search engines and readers. */
h1.wm { line-height: 0; }
h1.wm img { image-rendering: pixelated; display: block; }
.wm-text { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0);
           clip-path: inset(50%); white-space: nowrap; border: 0; }
header .tag { color: var(--muted); font-family: var(--head); font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
              white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
header .spacer { flex: 1; }
.hdr-globals { display: flex; align-items: center; gap: 8px; flex: none; }
.hdr-globals > button { padding: 6px 11px; white-space: nowrap; }
#build { flex: none; }
@media (max-width: 1280px) { header .tag:not(#build) { display: none; } }

#deps { display: none; padding: 6px 14px; background: #4d1418; color: #ffb3b8; font-weight: 700; }
#deps.show { display: block; }

/* ---- the generators: their own full-width row (CrunchyVFX §22.1) ---- */
.genbar { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 6px 14px;
          background: var(--bg); border-bottom: 1px solid var(--line); }
.genrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.genrow-keep { padding-left: 10px; border-left: 1px solid var(--line); }
.genbar button { padding: 5px 11px; }
.genkeep { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); cursor: pointer; }

/* ---- the picture strip: one cell per effect, PAGED by arrows, never a sideways scrollbar ---- */
#presetbar { flex: none; display: flex; flex-direction: column; gap: 5px; padding: 6px 14px 7px; background: var(--panel);
             border-bottom: 2px solid var(--drop); min-width: 0; }
.pbar-top { display: flex; align-items: center; gap: 10px; min-width: 0; }
.pbar-title { flex: none; font: 700 11px/1.5 var(--head); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
#stripSearch { flex: none; width: 180px; font-size: 12px; padding: 3px 8px; }
.pbar-chips { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; gap: 4px; }
.tagchip { font-size: 11px; padding: 1px 7px; background: var(--bg); border: 1px solid var(--line); box-shadow: none; color: var(--muted); white-space: nowrap; }
.tagchip:hover { color: var(--ink); border-color: var(--line2); }
.tagchip.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
#stripCount { flex: none; font-size: 11px; color: var(--muted); white-space: nowrap; }
.pbar-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.pstrip { display: flex; gap: 4px; flex: 1 1 auto; min-width: 0; overflow: hidden; }
.pcell { flex: none; width: 84px; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 4px 2px 3px;
         background: var(--panel2); border: 1px solid var(--line); box-shadow: none; cursor: pointer; }
.pcell:hover { border-color: var(--accent); }
.pcell.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.pcell.on .pname { color: var(--accent); }
.pcell canvas { width: 64px; height: 64px; image-rendering: pixelated; background: var(--bd-dark); display: block; }
.pname { width: 100%; font-size: 10.5px; line-height: 14px; color: var(--ink); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pfam { width: 100%; font-size: 9.5px; line-height: 12px; color: var(--muted); text-align: center; text-transform: uppercase; letter-spacing: .05em; }
.pnone { color: var(--muted); font-size: 12px; padding: 30px 4px; }
.pbar-row .pgbtn { flex: none; box-shadow: none; align-self: stretch; padding: 0 6px; font-size: 18px; line-height: 1; }
.pbar-row .tbarpage { flex: none; min-width: 40px; text-align: center; font-size: 11px; color: var(--muted); }

/* ---- the workspace: the editor (left), the preview (right), the Library docked last ---- */
.app { flex: 1; display: flex; min-height: 0; }
aside#editor { width: 330px; flex: none; overflow-y: auto; padding: 10px 12px 16px; background: var(--panel); border-right: 1px solid var(--line); }
aside h2 { margin: 14px 0 6px; padding-bottom: 3px; border-bottom: 1px solid var(--line); font: 700 11px/1.5 var(--head);
           text-transform: uppercase; letter-spacing: .1em; color: var(--ink); display: flex; align-items: baseline; gap: 8px; }
aside h2 .hint { margin-left: auto; font: 11px/1.5 var(--font); text-transform: none; letter-spacing: 0; color: var(--muted); }
.esec:first-child > h2 { margin-top: 0; }
aside h2.fold { cursor: pointer; user-select: none; }
aside h2.fold::before { content: "\2212"; display: inline-block; width: 10px; color: var(--muted); font-family: var(--font); }
aside .esec.folded > h2.fold::before { content: "+"; }
aside h2.fold:hover { color: var(--accent); }
aside h2.fold:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.esec.folded > .esec-body { display: none; }
.ctl { display: grid; grid-template-columns: 96px 1fr 58px; align-items: center; gap: 6px; margin: 5px 0; }
.ctl > label { color: var(--muted); font-size: 12px; line-height: 1.25; }
.ctl > .wide { grid-column: 2 / 4; }
.ctl output { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); font-size: 12px; }
.ctl input[type="text"] { width: 100%; padding: 3px 6px; }
.seg { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.seg button { padding: 3px 9px; font-size: 12px; }
.seg button.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 700; }
.ctl > .seg { grid-column: 2 / 4; }
.fxabout { margin: 6px 0; font-size: 12.5px; line-height: 1.45; color: var(--ink); }
.fxfacts { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0 8px; }
.fxfacts .fact { font-size: 11px; padding: 1px 6px; border: 1px solid var(--line); color: var(--muted); background: var(--bg); }
#resetBtn { font-size: 12px; padding: 3px 9px; }
.pcol input[type="color"], .palcell input[type="color"] { width: 100%; height: 22px; padding: 0 2px; background: var(--panel2); border: 1px solid var(--line); cursor: pointer; }
.pcol output { font-family: var(--mono, ui-monospace, monospace); font-size: 11px; }

/* a palette param: its swatches, + and ×, then the suite's palettes as chips */
.palrow { margin: 8px 0; padding: 6px; background: var(--panel2); border: 1px solid var(--line); }
.palhead { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.pallabel { font-size: 12px; color: var(--ink); }
.palhead .hint { font-size: 11px; color: var(--muted); margin-left: auto; }
.palsw { display: flex; flex-wrap: wrap; gap: 4px; }
.palcell { position: relative; width: 30px; }
.palcell input[type="color"] { height: 24px; }
.palx { position: absolute; top: -6px; right: -6px; width: 14px; height: 14px; padding: 0; font-size: 10px; line-height: 12px; box-shadow: none; }
.paladd { width: 30px; height: 24px; padding: 0; font-size: 14px; box-shadow: none; }
.palpre { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.palchip { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; padding: 2px 6px; box-shadow: none; }
.palchip.on { border-color: var(--accent); color: var(--accent); }
.palmini { display: inline-flex; height: 9px; border: 1px solid var(--drop); }
.palmini i { width: 5px; height: 100%; display: block; }

/* the subjects: picture buttons; your image; the backdrop */
.subjects { display: flex; flex-wrap: wrap; gap: 4px; margin: 5px 0; }
.subj { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; padding: 3px 4px 2px; font-size: 10.5px; box-shadow: none; min-width: 52px; }
.subj canvas { width: auto; height: 32px; image-rendering: pixelated; display: block; }
.subj.on { border-color: var(--accent); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.ownimg { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 8px 0; }
.ownimg button { font-size: 12px; padding: 3px 9px; }
.ownimg .hint { font-size: 11.5px; color: var(--muted); }

main#stage { flex: 1; min-width: 0; overflow: auto; padding: 14px 16px 18px; display: flex; flex-direction: column; gap: 12px; }
.stagehead { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.stagehead h2 { margin: 0; font: 700 15px/1.3 var(--head); text-transform: uppercase; letter-spacing: .03em; color: var(--ink); }
.stagehead .hint { font-size: 12px; color: var(--muted); }
figure { margin: 0; }
canvas.art { display: block; image-rendering: pixelated; border: 1px solid var(--line); }
/* the preview and its controls, the shader's code beside them when there is room (under them when there is not) */
.stagerow { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; min-width: 0; }
.pvcol { display: flex; flex-direction: column; gap: 10px; min-width: 0; max-width: 100%; }
.stagerow > #codePanel { flex: 1 1 340px; min-width: 300px; max-width: 100%; }
.viewbox { position: relative; align-self: flex-start; max-width: 100%; }
.viewbox canvas.art { max-width: 100%; }
.viewbox.zoomed { overflow: auto; max-height: max(220px, calc(100vh - 410px)); width: 100%; }
.viewbox.zoomed canvas.art { max-width: none; }
.zoomctl { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--muted); margin-left: auto; }
.zoomctl select { font-size: 12px; padding: 2px 4px; }
/* the live (WebGL2) preview sits exactly over the 2D canvas, which then holds only the backdrop */
.viewbox canvas.glview { position: absolute; left: 0; top: 0; }
.dropnote { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(8, 7, 12, 0.82);
            border: 2px dashed var(--accent); color: var(--accent); font-weight: 700; pointer-events: none; }
.fxbar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.fxbar button { padding: 3px 9px; font-size: 12px; }
.fxbar .hint { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.status { font-size: 12px; color: var(--muted); min-height: 1.5em; overflow-wrap: anywhere; max-width: 640px; }
.status:not(:empty) { color: var(--ink); }
.panel { background: var(--panel); border: 1px solid var(--line); padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.panel > h3 { margin: 0; font: 700 11px/1.5 var(--head); text-transform: uppercase; letter-spacing: .1em; color: var(--ink);
              display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.panel > h3 .hint { font: 11px/1.5 var(--font); text-transform: none; letter-spacing: 0; color: var(--muted); }
.codebar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.codebar > button { font-size: 12px; padding: 3px 9px; }
pre.code { margin: 0; max-height: 440px; overflow: auto; padding: 8px 10px; background: var(--bg); border: 1px solid var(--line);
           font: 11.5px/1.45 ui-monospace, Menlo, Consolas, monospace; color: var(--ink); white-space: pre; tab-size: 4; }

/* the Library (crunchyCore library.js), docked as the last column of the workspace */
.app > .lib-dock { width: 360px; flex: none; }

footer.license { flex: none; padding: 6px 14px; font-size: 12px; color: var(--muted); background: var(--panel); border-top: 1px solid var(--line); }
footer.license p { margin: 0; }
footer.license strong { color: var(--ink); }
footer.license .tool-notice { margin-top: 2px; }

/* THE WELCOME TOUR (CrunchyTile's, from CrunchyUI and CrunchyVFX): four plain panels around the hole, never a 9999 px
   box-shadow (that texture took a browser down in Tile), and nothing animates. */
.tour { position: fixed; inset: 0; z-index: 300; }
.tour-shade { position: absolute; background: rgba(8, 7, 12, 0.82); }
.tour-hole { position: absolute; border: 2px solid var(--accent); pointer-events: none; }
.tour-hole.notarget { border-color: transparent; }
.tour-card { position: absolute; width: min(360px, 90vw); background: var(--panel); border: 1px solid var(--line); padding: 14px 16px; box-shadow: var(--lift); }
.tour-title { font: 700 14px/1.4 var(--head); text-transform: uppercase; letter-spacing: .04em; color: var(--accent); margin-bottom: 6px; }
.tour-body { font-size: 13.5px; color: var(--ink); line-height: 1.5; }
.tour-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 14px; gap: 10px; }
.tour-progress { font-size: 12px; color: var(--muted); }
.tour-btns { display: flex; gap: 8px; }
.tour-btns button { padding: 6px 12px; font-size: 13px; }

/* PHONE WIDTH: the page stacks and scrolls as a whole, the preview first (what it makes), the editor after. */
@media (max-width: 760px) {
  html, body { height: auto; }
  header { flex-wrap: wrap; row-gap: 6px; }
  header .spacer { display: none; }
  .hdr-globals { flex: 1 1 100%; flex-wrap: wrap; gap: 6px; }
  .genrow-keep { padding-left: 0; border-left: 0; }
  #presetbar { padding: 6px 10px 7px; }
  .pbar-top { flex-wrap: wrap; row-gap: 4px; }
  #stripSearch { flex: 1 1 auto; width: auto; }
  .app { flex-direction: column; min-height: auto; }
  main#stage { order: -1; overflow: visible; padding: 10px; }
  aside#editor { width: auto; overflow: visible; border-right: none; border-top: 1px solid var(--line); }
  .app > .lib-dock { width: auto; }
  canvas.art { max-width: 100%; height: auto; }
  /* the shader's code scrolls in its own box, so the settings below are not 60 lines of GLSL away (usability round) */
  #codePanel .code { max-height: 34vh; overflow: auto; }
}

/* usability round (2026-10-15): a palette that matches nothing on the picture says so */
.palnote:empty { display: none; }
.palnote.warn { color: #ffcf6e; margin: 4px 0 0; }
.ctl > select { grid-column: 2 / 4; font-size: 12px; padding: 2px 4px; }
.code.wrap { white-space: pre-wrap; overflow-wrap: anywhere; }

/* §14 COMBOS (css-build 4): one button beside Save and its panel, dropped below it (CrunchyTile's Kits panel). */
.combomenu { position: relative; }
#comboBtn.on { border-color: var(--accent); }
.combopanel { position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 40; width: 380px; max-width: 90vw; display: flex;
              flex-direction: column; gap: 8px; padding: 12px; background: var(--panel); border: 2px solid var(--accent);
              box-shadow: 0 4px 0 var(--drop); }
.combopanel[hidden] { display: none; }
.comborow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.comborow label { font-size: 12px; opacity: .75; width: 3.5em; }
.comborow select, .comborow input { flex: 1 1 10em; min-width: 0; }
.comborow[hidden] { display: none; }
.combolayers { margin: 0; padding: 0 0 0 1.6em; display: flex; flex-direction: column-reverse; gap: 4px; }
.combolayers:empty { display: none; }
.combolayers li { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.combolayers li .lname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.combolayers li select { font-size: 11px; }
.combolayers li button { padding: 1px 6px; font-size: 11px; }
.combolayers li .lstate { width: 6.5em; flex: 0 0 auto; font-size: 11px; padding: 1px 4px; }   /* §14.3 a layer's state name */
.combostates[hidden] { display: none; }
.combostates h4 { margin: 4px 0; font-size: 12px; color: var(--accent); }
.statechips { display: flex; flex-wrap: wrap; gap: 4px; }
.statechips:empty { display: none; }
.statechip { display: inline-flex; align-items: center; border: 1px solid var(--line); }
.statechip.auto { border-style: dashed; }   /* made from the layers' state names: no delete */
.statechip button { border: 0; box-shadow: none; padding: 2px 8px; font-size: 12px; }
.statechip.on { border-color: var(--accent); }
.statechip .sx { padding: 2px 5px; }
.combonote { font-size: 11px; color: var(--muted); }
.combonote:empty { display: none; }
#comboDelete.armed { color: #fff; background: #c0392b; }

/* SAVE ASKS (css-build 6): the core's dialog look (set-overlay / set-panel), narrower, its two buttons on the right */
.savepanel { width: min(460px, 100%); display: flex; flex-direction: column; gap: 10px; }
.savepanel .set-head { margin-bottom: 0; }
.saveacts { display: flex; justify-content: flex-end; gap: 8px; }

/* THE DESKTOP'S UPDATE BANNER (SHADER-DESIGN §18, css-build 7; CrunchyUI's): bottom center, over the page, under the
   dialogs. Square, the hard lift. Only the desktop ever shows it. */
.update-banner { position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 70;
  display: flex; align-items: center; gap: 12px; max-width: min(680px, 92vw);
  background: var(--panel); border: 2px solid var(--accent); padding: 10px 12px 10px 16px; box-shadow: var(--lift); font-size: 13px; }
.update-banner button { flex: none; padding: 6px 10px; font-size: 12px; }
#updMsg { margin-right: 8px; }

/* the web's About link in the license line (css-build 8; CrunchyTile's rule); hidden on the desktop ([data-web]) */
footer.license a.aboutlink { color: var(--accent); margin-left: 6px; white-space: nowrap; }

/* the Combos panel's one-line blend hint (css-build 9; usability round 2026-10-23) */
.combohint { margin: 0; font-size: 11px; color: var(--muted); line-height: 1.4; }
.combohint[hidden] { display: none; }
.combohint b { color: var(--ink); font-weight: 600; }
