/*
 * The two-pane wizard shared by the Model and Review Screens: a persistent
 * PDF Pratinjau pane beside a panel of form controls.
 *
 * Desktop is 808 + 448 with a 24 gap inside the 1280 container; tablet and
 * mobile stack the two, preview first.
 */

.wizard {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 1280px) {
  .wizard {
    /* 808 and 448 out of 1280, expressed as fractions so the pair still
       fills the container on wider screens. */
    grid-template-columns: minmax(0, 808fr) minmax(0, 448fr);
  }
}

/* -- Preview ---------------------------------------------------------- */

.preview {
  gap: var(--space-3);
}

.pager {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-base);
}

.pager__input {
  width: 41px;
  height: 32px;
  padding-inline: var(--space-1);
  background: var(--input-bg);
  border: none;
  border-radius: var(--radius-input);
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  text-align: center;
  color: var(--color-black);
}

.pager__input:focus-visible {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

.pager__total {
  color: var(--foreground);
  white-space: nowrap;
}

/* Paging was keyboard-only before this: type a number, or press an arrow key
   with the stage focused. Checking where one Page Range ends is a job of
   stepping page by page, so it gets controls you can see. */
.pager__step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: var(--input-bg);
  border: none;
  border-radius: var(--radius-input);
  color: var(--color-black);
  cursor: pointer;
}

.pager__step:disabled {
  opacity: 0.4;
  cursor: default;
}

.pager__step:focus-visible {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

.preview__stage {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  margin-inline: var(--space-5);
  padding: var(--space-4);
  min-height: 320px;
  background: var(--card);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-xl);
}

@media (min-width: 1280px) {
  .preview__stage {
    /* The 752px the design gives the page area at 1440. */
    min-height: 752px;
  }
}

.preview__stage:focus-visible {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

.preview__page {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.preview__note {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--muted-foreground);
  text-align: center;
}

/* Sits under the page rather than over it: the operator is comparing what the
   page shows against what the label claims, so it must not cover either. */
.preview__where {
  margin: 0;
  margin-inline: var(--space-5);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--muted-foreground);
  text-align: center;
}


/* -- Panel ------------------------------------------------------------ */

.panel {
  gap: var(--space-5);
}

/* Below 1280 the panel is free to grow with its content, same as any other
   stacked card — a long Run Log just makes the page taller. At 1280 it is a
   stretched item in wizard__side's explicit row, so its height is already the
   row's; min-height:0 is what lets it be shorter than its own text, which is
   what gives panel__log's flex:1 an actual bound to fill. Without it the log
   inflates the row and the page scrolls past it instead of the log scrolling
   in place.

   The height:0/min-height:100% pair that used to be here did this job back when
   the panel was a grid item of .wizard itself. It could not stay on the panel:
   the panel now shares a column with the Recent Slices card, whose track is
   content-sized, and a zero-height item makes a content-sized track zero too.
   It moved up to .wizard__side, which is the grid item of .wizard now. */
@media (min-width: 1280px) {
  .panel {
    min-height: 0;
  }
}

.panel__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-inline: var(--space-5);
}

.panel__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding-inline: var(--space-5);
}

/* Review's rows sit 16 apart rather than Model's 8 — its fields are pairs of
   boxes under a shared label, and 8 would read as one block of four. */
.panel__body--ranges {
  gap: var(--space-4);
}

/* A locked row dims whole, label included, as the design draws it (nodes
   32:3771 and 32:3792) — the same 0.5 a disabled button carries. Scoped to the
   ranges so it cannot reach the Model Screen's own disabled name field. */
.panel__body--ranges .field:has(.input:disabled) {
  opacity: 0.5;
}

/* -- A run in progress ------------------------------------------------ */

/* The Progress Screen is this same panel with its form locked, so the status
   line and the Run Log are further children of the card rather than cards of
   their own — as the design draws them (node 32:3760). */

.panel__status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  margin: 0;
  padding-inline: var(--space-5);
  font-size: var(--text-base);
  line-height: var(--leading-base);
  font-weight: var(--weight-medium);
  color: var(--foreground);
}

.spinner {
  width: 20px;
  height: 20px;
  flex: none;
  animation: spin 900ms linear infinite;
}

/* Spelled out rather than left to the UA stylesheet: `hidden` on an SVG
   element is not the well-trodden path it is on an HTML one, and a spinner
   still turning over a stopped run is the exact bug this prevents. */
.spinner[hidden] {
  display: none;
}

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation: none;
  }
}

/* Takes the remaining height of the card, which on desktop is as tall as the
   preview beside it. */
.panel__log {
  display: flex;
  flex: 1;
  min-height: 0;
  padding-inline: var(--space-5);
}

.log {
  flex: 1;
  min-height: 120px;
  margin: 0;
  padding: var(--space-5);
  overflow: auto;
  overscroll-behavior: contain;
  background: var(--color-black);
  border-radius: var(--radius-xl);
  color: var(--color-white);
  font-family: inherit;
  font-size: var(--text-base);
  line-height: var(--leading-base);
  font-weight: var(--weight-medium);
  /* Wrapped, not scrolled sideways: the lines that matter are long absolute
     paths, and the design wraps them rather than hiding their ends. */
  white-space: pre-wrap;
  word-break: break-word;
}

/* What to do with the Output, once there is one. The two wide buttons share
   the row evenly and the home button keeps its square. */
.panel__actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding-inline: var(--space-5);
}

/* -- Page Range row --------------------------------------------------- */

/* Two boxes under one label. They stay side by side at every width — the
   design keeps them paired down to 393, where each is half of 313. */
.range {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

/* -- The right-hand column -------------------------------------------- */
/*
 * The panel and the Recent Slices card share a column. Three arrangements,
 * one per breakpoint, exactly as the design draws them (node 32:2790):
 * stacked on mobile, side by side with the card first on tablet, and stacked
 * again on desktop where the card fills whatever the panel leaves.
 */

.wizard__side {
  display: grid;
  gap: var(--space-6);
  min-width: 0;
}

/* Tablet puts the card to the left of the panel — the one place in the design
   where reading order and DOM order part company. `order` rather than a
   reshuffled template, because the DOM order is the one screen readers and the
   tab sequence get, and the panel is what the operator came here to fill in. */
@media (min-width: 768px) and (max-width: 1279px) {
  .wizard__side {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .wizard__side > .recent-slices {
    order: -1;
  }
}

/* Desktop stacks them again, and the card takes the height the panel does not:
   its base lines up with the preview's, which is how the design says "fill".
   With no card on screen — a run in flight — the single track is 1fr and the
   panel takes the column itself, which is what keeps the Run Log clipping in
   place.

   height:0 / min-height:100% is what makes any of that hold. This column is a
   grid item of .wizard, and without it the column is sized by its own content:
   a long Run Log inflates the row, drags the Page Preview up to match, and the
   whole page scrolls past a log that never scrolls itself. Zero height keeps
   the column out of the row's auto sizing, so the preview alone settles it;
   min-height then puts the column back to that settled height. */
@media (min-width: 1280px) {
  .wizard__side {
    height: 0;
    min-height: 100%;
    grid-template-rows: minmax(0, 1fr);
  }

  .wizard__side:has(> .recent-slices:not([hidden])) {
    grid-template-rows: auto minmax(0, 1fr);
  }
}

/* -- Recent Slices ---------------------------------------------------- */

.recent-slices {
  gap: var(--space-5);
  /* Only ever shorter than its content on desktop, where it is a 1fr track. */
  min-height: 0;
}

.recent {
  flex: 1;
  min-height: 0;
  margin: 0;
  padding: 0;
  padding-inline: var(--space-5);
  list-style: none;
  /* Five rows is a fixed page (docs/adr/0019), and the card's height is whatever
     the panel leaves of the preview's — so whether five rows fit depends on the
     catalogue page on screen. Measured on a 358-page catalogue at 1280: 332px of
     rows into 284px of card. Without a scroll of its own, the pager would be
     pushed out through the bottom of the card. */
  overflow-y: auto;
}

.recent__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

/* 16 above the rule and 16 below it, as drawn. A gap on the list would only
   give the first of those. */
.recent__row + .recent__row {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: var(--border-width) solid var(--border);
}

/* The mark and the name are one target, which is what the design's Frame 26
   groups them into — and why hovering lights both at once. */
.recent__link {
  display: flex;
  flex: 1;
  align-items: center;
  gap: var(--space-4);
  min-width: 0;
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius-xl);
}

.recent__link:focus-visible {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

.recent__mark {
  position: relative;
  flex: none;
  width: 40px;
  height: 40px;
}

/* Both faces are in the DOM and stacked, so the red one is already loaded when
   the cursor arrives. Swapping a background-image on hover would fetch it at
   the moment it is needed, and show the gap. */
.recent__face {
  position: absolute;
  inset: 0;
  width: 40px;
  height: 40px;
}

.recent__face--active {
  opacity: 0;
}

.recent__link:hover .recent__face--active,
.recent__link:focus-visible .recent__face--active {
  opacity: 1;
}

/* The design steps the name from Medium to Bold on hover. Only Regular and
   Medium are bundled (ADR-0001 rules out a build step, and a third face is a
   third download), so the step is drawn with the two faces the app actually
   has rather than asking the browser to synthesise a bold it was never given. */
.recent__name {
  overflow: hidden;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--color-black);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.recent__link:hover .recent__name,
.recent__link:focus-visible .recent__name {
  font-weight: var(--weight-medium);
}

.recent__actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-2-5);
}

/* The card's pager sits on the card rather than inside a header, so it carries
   the gutter itself. Right-aligned and spaced 16 apart, as drawn (node 136:532). */
.pager--end {
  justify-content: flex-end;
  gap: var(--space-4);
  padding-inline: var(--space-5);
}
