:root{
  --ground:#151827; --panel:#1D2135; --panel-2:#252A42; --rule:#343A5C;
  --ink:#EDEEF5; --ink-dim:#8D93B5;
  --a:#FF3366; --b:#33CCCC; --c:#FFCC00;
  /* --a as a fill clears nothing in particular; --a as *text* was 4.48:1 on
     --panel and 3.98:1 on --panel-2, under AA either way. --a-ink is the same
     pink lightened until the worst of the three grounds passes (4.73:1), so
     lanes and swatches keep the saturated brand colour and prose stays legible. */
  --a-ink:#FF5A82;
  /* The selected state of a control that is not about base, overlay or output.
     It used to be --c, which is why --c stopped meaning anything. */
  --sel:#39406A;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --ui: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--ground);color:var(--ink);font-family:var(--ui);font-size:14px;
     line-height:1.5;padding:20px;min-height:100vh}
.wrap{max-width:1180px;margin:0 auto}
header{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:2px}
header svg{display:block;border-radius:6px}
h1{font-family:var(--mono);font-size:16px;letter-spacing:.22em;text-transform:uppercase;
   font-weight:600;margin:0}
.tag{font-family:var(--mono);font-size:11px;color:var(--ink-dim);letter-spacing:.06em}
.lede{color:var(--ink-dim);max-width:60ch;margin:10px 0 22px;font-size:13.5px;line-height:1.65}
/* Both columns are told to fill the row, so the taller one -- in practice the
   controls -- sets the height and the preview grows into it instead of leaving
   the bottom half of the page empty. */
.grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:16px;align-items:stretch}
.col{display:flex;flex-direction:column;gap:16px;min-width:0}
.col.main > .panel.grow{flex:1;display:flex;flex-direction:column;min-height:0}
@media(max-width:860px){
  .grid{grid-template-columns:minmax(0,1fr)}
  /* Stacked, there is no second column to match, so an unbounded preview would
     push the controls off the screen. */
  .col.main > .panel.grow{flex:none}
  .stage{min-height:300px}
}
.panel{background:var(--panel);border:1px solid var(--rule);border-radius:4px;
  /* A hairline of light along the top edge, so a panel reads as raised from the
     ground rather than drawn on it. Cheaper than a shadow and does not smudge. */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04)}
/* A panel title and a field label used to be the same thing to look at -- 10px,
   dim, uppercase, mono -- so nothing said which was the heading. The title is
   brighter now, a size larger, and sits on its own band. */
.panel h2{font-family:var(--mono);font-size:11px;letter-spacing:.2em;text-transform:uppercase;
   color:var(--ink);margin:0;padding:11px 14px;background:var(--panel-2);
   border-bottom:1px solid var(--rule);border-radius:3px 3px 0 0;font-weight:600}
.pad{padding:14px}
.slots{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.slot{border:1px dashed var(--rule);border-radius:3px;background:var(--panel-2);padding:10px;
      cursor:pointer;min-height:120px;display:flex;flex-direction:column;gap:7px;
      transition:border-color .12s,background .12s}
.slot:hover,.slot.hot{background:#2A3050}
.slot[data-i="0"]:hover,.slot[data-i="0"].hot{border-color:var(--a)}
.slot[data-i="1"]:hover,.slot[data-i="1"].hot{border-color:var(--b)}
.slot .lbl{font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase}
.slot[data-i="0"] .lbl{color:var(--a-ink)}
.slot[data-i="1"] .lbl{color:var(--b)}
.slot .hint{color:var(--ink-dim);font-size:12px;margin:auto 0}
.slot .meta{font-family:var(--mono);font-size:11px;color:var(--ink-dim);margin-top:auto}
.slot .name{font-size:12px;word-break:break-all;color:var(--ink);line-height:1.3}
.slot .thumb{width:100%;height:56px;object-fit:contain;border-radius:2px;background:
  conic-gradient(#20243a 0 25%,#191d30 0 50%,#20243a 0 75%,#191d30 0) 0/12px 12px}
input[type=file]{display:none}
.stage{position:relative;display:flex;align-items:center;justify-content:center;padding:16px;
  min-height:340px;flex:1;overflow:hidden;
  background:conic-gradient(#20243a 0 25%,#191d30 0 50%,#20243a 0 75%,#191d30 0) 0/16px 16px;
  border-bottom:1px solid var(--rule)}
/* Out of flow on purpose. As a flex item the canvas contributed its own size
   to the column, so fitting it to the panel made the panel taller, which made
   the fit larger, which made the canvas bigger again -- a loop that settled at
   different scales in different engines and ran to the maximum in Firefox.
   Absolute inside the relative .stage, it can no longer size its ancestors,
   and inset:0 with margin:auto centres it at whatever size it is given. */
#stage{position:absolute;inset:0;margin:auto;
  image-rendering:pixelated;cursor:grab;border-radius:2px;
  box-shadow:0 0 0 1px rgba(255,255,255,.07)}
#stage.drag{cursor:grabbing}
#stage:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
#stage[hidden]{display:none}

/* Before anything is loaded the stage was simply blank, which told a first
   visitor nothing about where to begin. */
.empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:9px;text-align:center;padding:24px;pointer-events:none}
/* .empty's own display would otherwise win over the hidden attribute. */
.empty[hidden]{display:none}
.empty .up{font-size:17px;color:var(--ink-dim);line-height:1}
.empty .big{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink)}
.empty .sub{font-size:12px;color:var(--ink-dim);max-width:36ch;line-height:1.6}
.empty .fmts{font-family:var(--mono);font-size:10px;letter-spacing:.1em;color:var(--ink-dim);
  text-transform:uppercase;opacity:.75}
.stagebar{display:flex;gap:10px;align-items:center;padding:8px 12px;flex-wrap:wrap;
  font-family:var(--mono);font-size:11px;color:var(--ink-dim)}
.stagebar .sep{flex:1}
.zoom{display:flex;align-items:center;gap:4px}
.zoom button{width:auto;padding:4px 9px;font-family:var(--mono);font-size:11px;line-height:1.2}
.zoom .pct{min-width:54px;text-align:center;color:var(--ink);font-variant-numeric:tabular-nums}
.zoom button[aria-pressed=true]{background:var(--sel);border-color:#4A5285;color:var(--ink)}
#timeline{width:100%;height:118px;display:block}
.legend{display:flex;gap:16px;padding:0 12px 10px;font-family:var(--mono);font-size:10px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-dim);flex-wrap:wrap}
.legend i{width:9px;height:9px;display:inline-block;margin-right:6px;border-radius:1px}
.ctl{margin-bottom:17px}
.ctl:last-child{margin-bottom:0}
.ctl[hidden]{display:none}
label.k{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-dim);margin-bottom:6px}
select,button,input[type=number]{font-family:var(--ui);font-size:13px;color:var(--ink);
  background:var(--panel-2);border:1px solid var(--rule);border-radius:3px;padding:8px 9px;
  /* border-color only. Transitioning the background made a segmented control
     fade into its selected state over 120ms, so the control lagged the thing it
     was reporting -- and a test reading the colour straight after the click saw
     the old one, which is exactly what a user's eye sees too. State is
     instant; the hover outline can afford to ease. */
  width:100%;transition:border-color .12s}
select:focus-visible,button:focus-visible,input:focus-visible,.slot:focus-visible{
  outline:2px solid var(--ink);outline-offset:1px}
input[type=range]{width:100%;accent-color:var(--ink-dim);background:transparent}
input[type=color]{width:100%;height:32px;padding:2px;background:var(--panel-2);
  border:1px solid var(--rule);border-radius:2px}
.val{font-family:var(--mono);font-size:11px;color:var(--ink);float:right}
.val.unit{color:var(--ink-dim)}
.pair{display:grid;grid-template-columns:1fr 1fr;gap:6px}
button:disabled{opacity:.4;cursor:not-allowed}
.xy{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.xy label{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:11px;
  color:var(--ink-dim)}
.xy input{width:100%;font-family:var(--mono);font-variant-numeric:tabular-nums}
/* Announcements for a screen reader, and nothing for anyone else. Not
   display:none, which would take it out of the accessibility tree too. */
.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.seg{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.seg button{padding:6px}
.seg button[aria-pressed=true]{background:var(--sel);color:var(--ink);
  border-color:#4A5285;font-weight:600}
/* The one segmented control that really is about the two lanes. */
.seg #lyBase[aria-pressed=true]{background:var(--a);color:#151827;border-color:var(--a)}
.seg #lyOver[aria-pressed=true]{background:var(--b);color:#151827;border-color:var(--b)}
button{cursor:pointer}
button:hover{border-color:var(--ink-dim);background:#2E3454}
select:hover{border-color:var(--ink-dim)}
/* The native control is the one thing on the page still drawn by the browser,
   so it reads as borrowed. appearance:none takes the chrome off and the chevron
   comes back as a background image -- inline SVG rather than a glyph, because a
   glyph would pick up the UI font and shift between platforms. Padded on the
   right so long labels cannot run under it. */
select{appearance:none;-webkit-appearance:none;padding-right:30px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238D93B5' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center;background-size:10px 6px}
select:hover{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23EDEEF5' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E")}
/* The plain actions -- swap, recentre, undo -- stay transparent until pointed
   at, so they read as available rather than as another segmented control. */
.ghost:hover:not(:disabled){background:var(--panel-2)}
.go{background:var(--c);color:#151827;border-color:var(--c);font-weight:600;padding:11px;
  font-family:var(--mono);letter-spacing:.12em;text-transform:uppercase;font-size:12px}
.go:hover{filter:brightness(1.08)}
.go:disabled{opacity:.4;cursor:not-allowed;filter:none}
.go.stop{background:transparent;color:var(--a-ink);border-color:var(--a-ink);margin-top:6px}
.ghost{background:transparent}
.readout{font-family:var(--mono);font-size:11px;line-height:1.85;color:var(--ink-dim)}
.readout b{color:var(--ink);font-weight:600}

/* The plan is what tells you whether the merge did what you wanted, so it sits
   under the timeline it describes rather than halfway down a panel of sliders,
   and the output figures are the largest text on the page after the title. */
.plan{padding:11px 12px;background:var(--panel-2);border-top:1px solid var(--rule);
  font-family:var(--mono)}
.plan .out{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
.plan .out .k{font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--c)}
.plan .fig{font-size:18px;font-weight:600;color:var(--c);line-height:1.15;
  font-variant-numeric:tabular-nums}
.plan .fig .u{font-size:11px;font-weight:400;color:var(--ink-dim);margin-left:3px}
.plan .in{display:flex;gap:20px;flex-wrap:wrap;font-size:11px;color:var(--ink-dim);
  margin-top:7px}
.plan .in .k{font-size:10px;letter-spacing:.14em;text-transform:uppercase;margin-right:6px}
.plan .in .base .k{color:var(--a-ink)}
.plan .in .over .k{color:var(--b)}
.plan .in b{color:var(--ink);font-weight:600}
.plan .status{font-size:11px;margin-top:8px;padding-top:8px;border-top:1px solid var(--rule)}
.plan .idle{font-size:11px;color:var(--ink-dim)}
.warn{color:var(--a-ink)} .ok{color:var(--b)}
.note{font-size:12px;color:var(--ink-dim);margin-top:6px}
#out{margin-top:12px}
#out .prev{width:100%;border-radius:2px;display:block;background:
  conic-gradient(#20243a 0 25%,#191d30 0 50%,#20243a 0 75%,#191d30 0) 0/12px 12px}
#out a.dl{display:block;text-align:center;margin-top:8px;text-decoration:none;
  font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  padding:10px;border:1px solid var(--c);color:var(--c);border-radius:2px}
#out a.dl:hover{background:var(--c);color:#151827}
@media (prefers-reduced-motion: reduce){*{transition:none!important}}
