/* controls — rows, fields and the pattern picker.
   One label measure down the whole panel, one set of field styles, and the
   grid that picks a texture. */

/* ---- rows: fixed label measure, everything else takes the rest ----
   Flex rather than grid so the per-row column widths written inline in the
   markup no longer apply: one measure down the whole panel is what makes a
   dense inspector scannable. */
.row { display: flex; align-items: center; gap: 10px; min-height: var(--ctl); margin: 5px 0; }
/* The display above would otherwise beat `hidden`: a row a panel hides for
   the current setting (the CTA's solid-only and link-only rows) must go. */
.row[hidden] { display: none; }
.row > label { flex: 0 0 var(--lbl); color: var(--muted); letter-spacing: .01em; }
.row > input[type=range], .row > input[type=text], .row > select, .row > .chips, .row > div, .row > span {
  flex: 1 1 auto; min-width: 0;
}
/* A segmented control is as wide as its segments — stretching it would put air
   between the choices, which is the one thing that stops it reading as one
   control. */
.row > .radios { flex: 0 1 auto; }
.row > input[type=color], .row > input[type=checkbox] { flex: 0 0 auto; }
/* An inline label further into a row (the italic toggle) is a caption on the
   control beside it, not a row label — it takes no measure of its own. */
.row > span > label { color: var(--muted); cursor: pointer; }
.row > span > label:hover { color: var(--ink); }
/* A checkbox and its caption riding along at the end of a row. */
.row > span.inline-check { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.row > output {
  flex: 0 0 auto; min-width: 44px; text-align: right;
  font-variant-numeric: tabular-nums; font-weight: 500; color: var(--ink);
}

/* ---- fields ---- */
select, input[type=text], input[type=number] {
  width: 100%; height: var(--ctl); padding: 0 22px 0 7px;
  background: var(--bg); color: var(--ink);
  font: inherit; font-family: var(--ui-mono); font-size: 11px;
  border: 1px solid var(--ink); border-radius: 0;
}
select {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0h10L5 6z' fill='%23000'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 7px center; background-size: 8px 5px;
}
select:hover { background-color: var(--wash); }
input[type=text], input[type=number] { padding-right: 7px; }
/* A select sharing its row with a slider: as wide as its longest option and no
   wider, so the slider keeps the room. */
.row > select.narrow { flex: 0 0 70px; }

input[type=color] {
  width: 30px; height: var(--ctl); padding: 0;
  background: var(--bg); border: 1px solid var(--ink); border-radius: 0; cursor: pointer;
}
input[type=color]::-webkit-color-swatch-wrapper { padding: 2px; }
input[type=color]::-webkit-color-swatch { border: none; }

/* A master swatch whose layers disagree: the colour it shows is only the
   heading's, so it is marked rather than passed off as the shared value. */
input[type=color].is-mixed { border-style: dashed; border-color: var(--muted); }

input[type=checkbox] { width: 14px; height: 14px; margin: 0; accent-color: var(--ink); cursor: pointer; }

/* ---- sliders: a drawn line with a solid block riding it ---- */
input[type=range] { -webkit-appearance: none; appearance: none; height: 18px; background: transparent; cursor: pointer; }
input[type=range]::-webkit-slider-runnable-track { height: 1px; background: var(--ink); border: none; }
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 8px; height: 14px; margin-top: -6.5px;
  background: var(--ink); border: none; border-radius: 0; cursor: grab;
}
input[type=range]:hover::-webkit-slider-thumb { width: 10px; height: 16px; margin-top: -7.5px; }
input[type=range]:active::-webkit-slider-thumb { cursor: grabbing; }
input[type=range]::-moz-range-track { height: 1px; background: var(--ink); border: none; }
input[type=range]::-moz-range-thumb { width: 8px; height: 14px; background: var(--ink); border: none; border-radius: 0; cursor: grab; }
input[type=range]:hover::-moz-range-thumb { width: 10px; height: 16px; }
input[type=range]:active::-moz-range-thumb { cursor: grabbing; }

/* ---- buttons: outlined at rest, inverted under the pointer ---- */
button, .uploadbtn {
  height: var(--ctl); padding: 0 10px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--ink); border-radius: 0; cursor: pointer;
  font-family: var(--ui-mono); font-size: 10px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; white-space: nowrap;
  transition: background-color .12s ease, color .12s ease;
}
button:hover, .uploadbtn:hover { background: var(--ink); color: var(--bg); }
button:active, .uploadbtn:active { background: var(--muted); border-color: var(--muted); color: var(--bg); }
.uploadbtn { width: 100%; margin-top: 8px; }
/* The import control is a <label> wrapping a hidden file input, so inside a row
   it would otherwise take the label measure and the label colour. As an icon it
   is one of the buttons beside it. */
.row > label.uploadbtn { flex: 0 0 auto; width: auto; margin-top: 0; color: var(--ink); }
button.primary { background: var(--ink); color: var(--bg); }
button.primary:hover { background: var(--bg); color: var(--ink); }
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
/* A button row that follows fields rather than opening a section needs the gap
   the rows do not give it. */
.btnrow.spaced { margin-top: 8px; }
.btnrow button { flex: 1; }

/* ---- the visibility eye ----
   Photoshop's layer eye: shown is an open eye, hidden is the struck-through one
   and the whole button goes quiet, so a glance down the panel shows which
   layers are off. Both marks come from the same icon set as everything else. */
.eyebtn {
  position: relative; width: 22px; height: 18px; padding: 0; font-size: 0;
  background: transparent; border: 1px solid transparent; cursor: pointer;
}
.eyebtn:hover { border-color: var(--faint); }
.eyebtn::before {
  content: ""; display: block; width: 15px; height: 15px; margin: 0 auto;
  background: currentColor;
  -webkit-mask: var(--icon-eye) center / contain no-repeat;
  mask: var(--icon-eye) center / contain no-repeat;
}
.eyebtn[aria-pressed="false"] { color: var(--faint); }
.eyebtn[aria-pressed="false"]::before {
  -webkit-mask-image: var(--icon-eye-off);
  mask-image: var(--icon-eye-off);
}

/* small square controls — per-section randomize, panel toggle, lock */
/* ---- the marks on the buttons ----
   Every control that is a picture rather than a word draws it the same way: a
   mask in currentColor, so one drawing serves a white button and the inverted
   black one, and the picture is the button's own business rather than a glyph
   the markup has to carry. `data-mark` names which; `data-rand` needs no name
   because rolling something is always the same mark.

   The icons are Dashicons (GPL-2.0-or-later), inlined as tokens in base.css —
   see icons/sets/dashicons/ for the set and its licence. */
/* :where(), so this carries no specificity at all: it is the default mark for
   anything that rolls, and a data-mark below always outranks it — which is how
   the plate's dice keeps its own. Set on the element rather than on ::before,
   because a property set straight on the pseudo cannot be overridden by one
   inherited from the element. */
:where(button[data-rand], #randomize, #randFonts, #bgPhoto, #bgGradient, #sv-palRandom) { --mark: var(--icon-randomize); }

[data-mark="info"]      { --mark: var(--icon-info); }
[data-mark="minus"]     { --mark: var(--icon-minus); }
[data-mark="plus"]      { --mark: var(--icon-plus); }
[data-mark="download"]  { --mark: var(--icon-download); }
[data-mark="upload"]    { --mark: var(--icon-upload); }
[data-mark="db-export"] { --mark: var(--icon-db-export); }
[data-mark="refresh"]   { --mark: var(--icon-refresh); }
[data-mark="trash"]     { --mark: var(--icon-trash); }
[data-mark="star"]      { --mark: var(--icon-star); }
[data-mark="cloud"]     { --mark: var(--icon-cloud); }
[data-mark="undo"]      { --mark: var(--icon-undo); }
[data-mark="redo"]      { --mark: var(--icon-redo); }
/* The plate's dice fits the plate to the text rather than rolling it, and the
   mark it carries says so — which is why data-mark wins over data-rand here. */
[data-mark="expand"]    { --mark: var(--icon-expand); }

button[data-rand]::before,
#randomize::before, #randFonts::before,
#bgPhoto::before, #bgGradient::before, #sv-palRandom::before,
[data-mark]::before {
  content: ""; flex: none; width: 13px; height: 13px;
  background: currentColor;
  -webkit-mask: var(--mark) center / contain no-repeat;
  mask: var(--mark) center / contain no-repeat;
}

.iconbtn, .lockbtn {
  height: 18px; min-width: 20px; padding: 0 4px;
  font-size: 11px; font-weight: 400; letter-spacing: 0; text-transform: none;
}
/* The padlock: open while the layer is free to change, shut and inverted while
   it is held through a re-roll. `aria-pressed` is what the script sets and what
   a screen reader reads, so it is what draws the state too — there is no second
   place saying the same thing. */
.lockbtn { position: relative; width: 20px; padding: 0; font-size: 0; }
.lockbtn::before {
  content: ""; display: block; width: 14px; height: 14px; margin: 0 auto;
  background: currentColor;
  -webkit-mask: var(--icon-unlock) center / contain no-repeat;
  mask: var(--icon-unlock) center / contain no-repeat;
}
.lockbtn[aria-pressed="true"] { background: var(--ink); color: var(--bg); }
.lockbtn[aria-pressed="true"]::before {
  -webkit-mask-image: var(--icon-lock);
  mask-image: var(--icon-lock);
}

/* ---- segmented toggles: shared hairlines, solid black for the choice ---- */
.radios { display: flex; }
.radios input { display: none; }
.radios label {
  flex: 0 0 auto; height: var(--ctl); padding: 0 9px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--ui-mono); font-size: 10px; letter-spacing: .06em; cursor: pointer;
  color: var(--muted); background: var(--bg);
  border: 1px solid var(--ink); border-left: none;
  transition: background-color .12s ease, color .12s ease;
}
.radios label:first-of-type { border-left: 1px solid var(--ink); }
.radios label:hover { background: var(--wash); color: var(--ink); }
.radios label:has(input:checked) { color: var(--bg); background: var(--ink); }

/* ---- pattern picker ----
   Previews, so a grid rather than a <select>: an <option> cannot draw a tile.
   It sits open in the panel's flow rather than in a floating popup — the panel
   body is a scroll container and would clip one. */
.pat-grid {
  position: relative;      /* the offset parent the scroll maths measures against */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(28px, 1fr)); gap: 3px;
  margin: 6px 0; padding: 4px; max-height: 190px; overflow: auto;
  border: 1px solid var(--ink);
  scrollbar-width: thin; scrollbar-color: var(--faint) transparent;
}
.pat-grid::-webkit-scrollbar { width: 6px; }
.pat-grid::-webkit-scrollbar-thumb { background: var(--faint); }
/* The tile itself is an inline background-image, which is why the shared
   button:hover fill cannot wipe it — only the colour under it is overridden. */
.pat-grid button {
  height: auto; aspect-ratio: 1; padding: 0; border: 1px solid var(--faint);
  background-color: var(--bg); background-repeat: repeat;
}
.pat-grid button:hover { background-color: var(--wash); border-color: var(--ink); }
/* The current tile, in a grid of 87 near-identical squares: a black frame set
   off by a white gap, so it reads as picked from across the panel instead of
   as one more hairline. The name below spells it out. */
.pat-grid button[aria-pressed="true"] {
  border: 1px solid var(--bg);
  outline: 2px solid var(--ink); outline-offset: -3px;
  box-shadow: 0 0 0 2px var(--ink);
}
.pat-current {
  margin: -2px 0 2px; padding-left: 1px;
  font-family: var(--ui-mono); font-size: 10px; letter-spacing: .04em; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* weight chips — wrap, because a font can expose up to nine weights */
.chips { display: flex; flex-wrap: wrap; gap: 3px; }
.chips input { display: none; }
.chips label {
  height: 18px; padding: 0 6px;
  display: inline-flex; align-items: center;
  font-family: var(--ui-mono); font-size: 10px; letter-spacing: .04em; cursor: pointer;
  font-variant-numeric: tabular-nums;
  color: var(--muted); background: var(--bg); border: 1px solid var(--faint);
  transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}
.chips label:hover { border-color: var(--ink); color: var(--ink); }
.chips label:has(input:checked) { color: var(--bg); background: var(--ink); border-color: var(--ink); }

/* ---- running text: the one place the sans face is used ---- */
/* ---- the anchor ----
   Nine squares in the shape of what they mean: the window, and the point in it
   a position is measured from. The chosen one is filled, the rest are outlines,
   and there is no frame around the set — the nine squares already draw the
   rectangle they stand for. */
.anchorgrid {
  flex: 0 0 auto;
  display: grid; grid-template-columns: repeat(3, 10px); gap: 2px;
}
.anchorgrid button {
  width: 10px; height: 10px; min-width: 0; padding: 0;
  border: 1px solid var(--faint); background: var(--bg);
  transition: border-color .12s ease, background-color .12s ease;
}
.anchorgrid button:hover { border-color: var(--ink); background: var(--wash); }
.anchorgrid button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); }

/* ---- the scene list ----
   Open rather than a dropdown: a saved scene is something you browse, and a
   list you have to open first hides how much is in there. Same scroll box as
   the pattern and palette pickers, with a heading per source. */
.scenelist {
  position: relative;      /* the offset parent the scroll maths measures against */
  max-height: 168px; overflow: auto; margin: 2px 0 4px;
  border: 1px solid var(--ink);
  scrollbar-width: thin; scrollbar-color: var(--faint) transparent;
}
.scenelist::-webkit-scrollbar { width: 6px; }
.scenelist::-webkit-scrollbar-thumb { background: var(--faint); }
/* Where these live. Sticky, so the heading is still there when you are three
   folders down the box. A button: clicking it folds its group, the chevron
   says which way, and the count says what a shut one holds. */
.scenegroup {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; justify-content: flex-start; gap: 6px;
  width: 100%; height: auto; padding: 4px 6px 3px; background: var(--bg);
  border: 0; border-bottom: 1px solid var(--faint);
  font-family: var(--ui-mono); font-size: 9px; font-weight: 700; line-height: 1.4;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
  text-align: left; cursor: pointer;
}
.scenegroup:hover { background: var(--wash); color: var(--ink); }
.scenegroup::before {
  content: ''; flex: none; width: 0; height: 0;
  border-left: 4px solid currentColor; border-top: 3px solid transparent; border-bottom: 3px solid transparent;
  transition: transform .12s;
}
.scenegroup[aria-expanded="true"]::before { transform: rotate(90deg); }
.scenegroup .count { margin-left: auto; font-weight: 400; letter-spacing: .04em; }
.scenegroup ~ .scenegroup { border-top: 1px solid var(--faint); margin-top: 4px; }
.scenegroup-body[hidden] { display: none; }

/* Tabs, the way an Adobe panel draws them: a hairline under the row, and the
   open tab framed on three sides and joined to the content below it. The
   closed ones are words in grey. Undoes the shared button look, which would
   make each tab read as a command rather than as a place.

   The hairline is drawn by the row (::after, under the tabs), not as a border,
   so which tab covers it is a matter of stacking rather than of a -1px
   overlap: the open tab reaches down over it in the panel's own paper, and a
   closed one - hovered or not - stops a pixel short of it, so its wash never
   touches the rule. */
.tabs { position: relative; display: flex; align-items: flex-end; gap: 2px; margin: 6px 0 8px; }
.tabs::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--ink); }
.tabs button {
  position: relative; z-index: 1;
  height: 22px; margin: 0 0 1px; padding: 0 12px;
  background: transparent; color: var(--muted);
  border: 1px solid transparent; border-bottom: 0; box-shadow: none; transform: none;
  font-size: 10px; font-weight: 700; letter-spacing: .12em;
}
.tabs button:hover,
.tabs button:active { background: var(--wash); color: var(--ink); border-color: transparent; box-shadow: none; transform: none; }
.tabs button[aria-selected="true"] {
  height: 23px; margin-bottom: 0;
  background: var(--bg); color: var(--ink);
  border-color: var(--ink);
}
.tabpane[hidden] { display: none; }
/* A block rather than the flex the other buttons are: the name is one line that
   has to trail off when it is too long, and ellipsis needs a block to do it. */
.scenerow {
  display: block; width: 100%; height: 20px; padding: 0 6px;
  border: 0; background: var(--bg); color: var(--muted);
  font-family: var(--ui-mono); font-size: 10px; font-weight: 400; line-height: 20px;
  letter-spacing: .02em; text-transform: none; text-align: left;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.scenerow:hover { background: var(--wash); color: var(--ink); }
.scenerow[aria-pressed="true"] { background: var(--ink); color: var(--bg); }
/* A local scene that is only in this browser, not in local-scenes.json yet. */
.scenerow.is-browser-only::before { content: '• '; }
.scene-empty {
  margin: 0; padding: 7px 6px;
  font-family: var(--ui-mono); font-size: 10px; color: var(--muted);
}

.hint {
  margin: 8px 0 0;
  font-family: var(--ui-sans); font-size: 11px; line-height: 1.6; color: var(--muted);
}
.hint b { color: var(--ink); font-weight: 600; }
/* Nothing to say, nothing to take up room: a note with no message left in it
   would still hold its margin open. */
.hint:empty { display: none; }
.hint a { color: var(--ink); }

@media (max-width: 760px) { .panel { width: min(88vw, 360px); } }
@media (prefers-reduced-motion: reduce) {
  .panel, button, .uploadbtn, .radios label, .chips label, .chev { transition: none; }
}

/* Ensure elements like `nsc-project-*` use the ink color for their background */
[class^="nsc-project-"], [class*=" nsc-project-"] {
  background-color: var(--color-ink) !important;
  color: inherit;
}
