/* ============================================================
   Signal — tool-specific styling.
   Loaded after tokens, components and the app shell.
   ============================================================ */

/* Two columns, not three: there is no list here, and a panel filled with
   padding is worse than a panel that does not exist.

   Held inside a min-width query on purpose. The shell stacks its panels under
   960px from a media block of its own, and this file loads after it, so an
   unconditional rule wins on source order alone and the phone layout silently
   goes back to columns. */
@media (min-width: 961px) {
  .workspace {
    grid-template-columns: minmax(0, 1fr) 320px;
    /* A row that cannot exceed the height it was given. Left at auto, a grid
       row grows to fit its content, and the content here is a canvas sized
       from the row — so a tall image would quietly push the page open instead
       of being scaled down into it. */
    grid-template-rows: minmax(0, 1fr);
  }
}
@media (min-width: 961px) and (max-width: 1180px) {
  .workspace { grid-template-columns: minmax(0, 1fr) 292px; }
}

/* ---------- the stage ---------- */

.viewport {
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  /* Even on all four sides, so the picture sits in the middle of the panel
     rather than pushed up by a strip held open for the dock. The dock floats
     over the canvas, the way it does in every tool here. */
  padding: 28px;
  min-height: 0;
  min-width: 0;
}

.stage-wrap {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
}

.viewport canvas#stage {
  display: block;
  /* Width and height are written on by the renderer; these are the backstop
     for the frame before the first measurement lands. */
  max-width: 100%;
  max-height: 100%;
  border-radius: var(--md-sys-shape-corner-medium);
  box-shadow: var(--app-hairline);
  /* Nearest, because this is the one tool where the pixels are the point: a
     sorted run smoothed by the browser is a sorted run you cannot see. */
  /* Auto, not pixelated: on a high-density screen the canvas is drawn bigger
     than it is shown, and nearest-neighbour on a downscale is aliasing rather
     than crispness. */
  image-rendering: auto;
}

/* While the sort is catching up. Not a spinner over the picture — the frame on
   screen is still the last real one, and covering it would hide the thing you
   are trying to judge. A thin line at the top of the stage says work is
   happening and takes nothing away. */
.stage-wrap::after {
  content: "";
  position: absolute; left: 0; right: 0; top: -4px; height: 2px;
  border-radius: 2px;
  background: var(--md-sys-color-primary);
  opacity: 0;
  transform: scaleX(0.2);
  transition: opacity var(--md-sys-motion-duration-short) var(--md-sys-motion-standard);
}
body[data-sorting="true"] .stage-wrap::after {
  opacity: 0.9;
  animation: sorting 900ms var(--md-sys-motion-standard) infinite;
}
@keyframes sorting {
  0% { transform: scaleX(0.15); transform-origin: left; }
  50% { transform: scaleX(1); transform-origin: left; }
  100% { transform: scaleX(0.15); transform-origin: right; }
}
@media (prefers-reduced-motion: reduce) {
  body[data-sorting="true"] .stage-wrap::after { animation: none; transform: scaleX(1); }
}

/* ---------- inspector ---------- */

.panel--inspector .controls {
  display: flex; flex-direction: column; gap: 14px;
  padding: 4px 4px 12px;
}

/* Headings, not disclosures. Nine sliders want grouping; none of them wants
   hiding, and a group you can fold away is a place for a control to get lost. */
.group-title {
  margin: 10px 0 -4px;
  font: 500 11px/16px var(--md-sys-typescale-plain-font);
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--md-sys-color-on-surface-variant);
}
.group-title:first-child { margin-top: 0; }

.md-segmented button { flex: 1 1 auto; min-width: 44px; }

/* ---------- the export dialog ---------- */

.md-dialog { max-width: 420px; }
.dialog-note {
  margin: 0 0 18px;
  font: 400 13px/19px var(--md-sys-typescale-plain-font);
  color: var(--md-sys-color-on-surface-variant);
}
.dialog-meta {
  margin: 14px 0 0;
  font: 400 12px/17px var(--md-sys-typescale-plain-font);
  color: var(--md-sys-color-on-surface-variant);
  font-variant-numeric: tabular-nums;
}
.export-row { display: flex; flex-wrap: wrap; gap: 8px; }
.export-row .md-button { flex: 1 1 auto; justify-content: center; font-variant-numeric: tabular-nums; }

.dialog-heading {
  margin: 26px 0 6px;
  font: 500 14px/20px var(--md-sys-typescale-plain-font);
  letter-spacing: 0.1px;
}
#export-progress { margin-top: 12px; }

/* The export dialog carries two lists now, which is taller than the house
   dialog was drawn for. On a short window the list scrolls and the Close button
   stays put, rather than the whole thing running off the bottom of the screen.
   Only when it is open: a closed dialog is display:none by the browser's own
   rule, and setting display on the element itself overrides that and lays the
   whole thing out in the page. */
#dlg-export {
  flex-direction: column;
  max-height: calc(100dvh - 48px);
}
#dlg-export[open] { display: flex; }
#dlg-export .content { min-height: 0; overflow-y: auto; }

/* ---------- narrow ---------- */

@media (max-width: 960px) {
  /* How tall the picture is, written once: the shell sizes both the grid row
     and the viewport's own minimum, and setting only one of them makes the
     viewport overflow its row and print the panel over its own canvas. */
  .workspace {
    --picture: max(320px, 44dvh);
    grid-template-rows: var(--picture) auto;
    gap: 20px;
  }
  .viewport { padding: 12px; min-height: var(--picture); }
}

@media (max-width: 720px) {
  /* Expanded, the hint has to cross the credit badge, so it goes over it. */
  .viewport-hint[aria-expanded="true"] { z-index: 6; }
  .viewport-hint[aria-expanded="true"] .text { max-width: calc(100vw - 108px); }
}

/* A bar of five buttons and a title does not fit across a phone, and a bar that
   overflows widens the page under it rather than scrolling — which cuts off the
   canvas, the panel and the badge at the right. Everything with a word on it
   loses the word. */
@media (max-width: 620px) {
  .md-top-app-bar { gap: 2px; padding: 0 6px 0 10px; }
  .md-top-app-bar .brand { display: none; }
  /* The shortcuts list is no use without a keyboard, and this is the width
     where there is unlikely to be one. */
  .md-top-app-bar #btn-shortcuts { display: none; }
  .md-top-app-bar .md-button.has-icon {
    width: 40px; padding: 0; gap: 0; font-size: 0;
  }
  .md-top-app-bar .md-button.has-icon svg { width: 20px; height: 20px; }
}

/* ---------- "Powered by" credit ----------
   Lives in the DOM on top of the canvas, never inside it, so it is present
   while you work and absent from every export. */
.viewport-credit {
  /* One number controls the whole badge: the artwork is 100x32 at scale 1. */
  --credit-scale: 2;
  position: absolute; top: 12px; right: 12px; z-index: 5;
  display: block; padding: 0; line-height: 0;
  border-radius: calc(9px * var(--credit-scale)); overflow: hidden;
  background: color-mix(in srgb, var(--md-sys-color-surface-container-high) 82%, transparent);
  backdrop-filter: blur(12px);
  box-shadow: var(--app-hairline);
  transition: background-color var(--md-sys-motion-duration-short) var(--md-sys-motion-standard);
}
.viewport-credit:hover { background: var(--md-sys-color-surface-container-high); }
.viewport-credit svg {
  display: block;
  width: calc(100px * var(--credit-scale));
  height: calc(32px * var(--credit-scale));
}
.viewport-credit .credit-label { fill: var(--md-sys-color-on-surface-variant); }
.viewport-credit .credit-name,
.viewport-credit .credit-mark { fill: var(--md-sys-color-on-surface); }

/* Step it back on narrow viewports so it cannot run into the hint chip. */
@media (max-width: 1180px) { .viewport-credit { --credit-scale: 1.5; } }
@media (max-width: 960px)  { .viewport-credit { --credit-scale: 1.25; } }
