/*
 * Shimti Multimedia - the workbench
 *
 * Styling for the instruments on the Services page. They live inside the page sheet, so they
 * inherit its ink palette rather than the interface's glow.
 *
 * @requires assets/scripts/components/workbench.js
 */

.bench {
  margin: 0 0 2.5rem;

  /*
   * Narrower than the reading column on purpose.
   *
   * The page image at the top is the full measure, and an instrument set to the same
   * width competes with it - the eye reads two things of equal weight and cannot tell
   * which is the subject. Capped in rem rather than as a percentage so the instruments
   * stay the same physical size as the column widens, which keeps them subordinate.
   *
   * Everything inside inherits the cap, so the stage, the title, the note and the
   * controls all stay on one edge instead of the controls hanging off a narrower image.
   */
  max-width: 32rem;
}


.bench-title {
  margin: 0 0 0.35rem;
  font-size: clamp(1rem, 2.2vw, 1.3rem);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.bench-note {
  margin: 0 0 1rem;
  color: var(--muted-color);
  font-size: clamp(0.8rem, 1.7vw, 0.92rem);
}

.bench-stage {
  position: relative;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  overflow: hidden;
  /* Reserved before the images arrive, so nothing below jumps as they load. */
  aspect-ratio: 16 / 9;
  background: #0b0e13;
}

.bench-stage img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ------------------------------------------------------------------- reveal */

/*
 * The finished version sits on top and is clipped to the handle. inset() clips rather than
 * resizes, so both images stay the same size and the seam moves across a single picture
 * instead of squashing one half of it.
 */
.bench-clip {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--reveal, 50%)) 0 0);
}

/* The seam, so the boundary is visible rather than merely implied. */
.bench-clip::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 2px;
  background: #eaffff;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
}

/*
 * Shared appearance for both controls. Positioning is NOT here, deliberately.
 *
 * It used to be: this rule carried position:absolute and inset:0 so the reveal handle could
 * lie across its image. The turntable's scrub wears the same class for its thumb styling
 * and inherited all of it - and with no positioned ancestor it resolved against the
 * viewport, stretched over the entire window, and pushed its own top margin past the
 * bottom edge. Twelve pixels of scroll on a layout whose whole premise is that the window
 * does not scroll, from a slider that was supposed to be sitting under a picture.
 *
 * Layout belongs to whichever instrument needs it, so it lives with them below.
 */
.bench-range {
  margin: 0;
  padding: 0;
  appearance: none;
  background: transparent;
  cursor: ew-resize;
}

/*
 * Reveal only: the control lies across the whole stage, invisible, so the image itself is
 * draggable and the thumb is all that is seen.
 */
[data-bench="reveal"] .bench-range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.reveal-nav {
  position: absolute;
  top: 50%;
  z-index: 4;
  width: 2.25rem;
  height: 3rem;
  padding: 0.35rem;
  border: 0;
  color: #effcff;
  background: rgba(2, 10, 16, 0.72);
  transform: translateY(-50%);
  cursor: pointer;
}

.reveal-nav--previous { left: 0; border-radius: 0 0.45rem 0.45rem 0; }
.reveal-nav--next { right: 0; border-radius: 0.45rem 0 0 0.45rem; }
.reveal-nav svg { display: block; width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.reveal-nav:hover, .reveal-nav:focus-visible { color: #8deaff; background: rgba(2, 17, 27, 0.9); }
.reveal-nav:focus-visible { outline: 2px solid white; outline-offset: -3px; }

.reveal-status {
  position: absolute;
  left: 50%;
  bottom: 0.45rem;
  z-index: 4;
  padding: 0.25rem 0.55rem;
  border: 1px solid rgba(141, 234, 255, 0.7);
  border-radius: 1rem;
  color: #effcff;
  background: rgba(2, 10, 16, 0.78);
  font-size: 0.65rem;
  transform: translateX(-50%);
  pointer-events: none;
}

@media (max-width: 56.249em) {
  .reveal-nav { width: 1.75rem; height: 2.5rem; padding: 0.25rem; }
  .reveal-status { bottom: 0.3rem; font-size: 0.58rem; }
}

.bench-range::-webkit-slider-thumb {
  appearance: none;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  border: 2px solid #eaffff;
  background: rgba(5, 7, 11, 0.65);
  backdrop-filter: blur(2px);
  cursor: ew-resize;
}

.bench-range::-moz-range-thumb {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  border: 2px solid #eaffff;
  background: rgba(5, 7, 11, 0.65);
  cursor: ew-resize;
}

.bench-range:focus-visible {
  outline: 3px solid var(--focus-outline);
  outline-offset: 3px;
}

/* --------------------------------------------------------------- turntable */

/*
 * The turntable's control sits under its stage rather than over it: a rotation wants a
 * visible position, and an invisible handle would give no sense of where in the spin you
 * are.
 */
.bench-scrub {
  position: static;
  display: block;
  width: 100%;
  height: auto;
  margin: 0.75rem 0 0;
  accent-color: var(--accent);
  /* Left as the platform draws it: a visible track communicates position in a rotation,
     which is the one thing the reveal handle deliberately hides. */
  appearance: auto;
  cursor: grab;
}

.bench-scrub:focus-visible {
  outline: 3px solid var(--focus-outline);
  outline-offset: 3px;
}

/* ------------------------------------------------------------------- grade */

.bench-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.75rem 0 0;
}

.bench-option {
  /* 24px minimum target, per WCAG 2.5.8. */
  min-height: 2.25rem;
  padding: 0.35rem 0.9rem;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: clamp(0.75rem, 1.5vw, 0.85rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.bench-option:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.bench-option[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #ffffff;
}

.bench-option:focus-visible {
  outline: 3px solid var(--focus-outline);
  outline-offset: 2px;
}

/*
 * Grades as filters.
 *
 * Placeholders that stand in for real colour work: a look is a curve, not a filter stack.
 * They are here so the instrument can be operated and judged before the real frames exist,
 * and each is replaced by a graded still rather than tuned.
 */
.bench-stage[data-grade="neutral"] img { filter: none; }
.bench-stage[data-grade="warm"] img { filter: saturate(1.15) sepia(0.22) hue-rotate(-12deg) contrast(1.05); }
.bench-stage[data-grade="cool"] img { filter: saturate(1.1) hue-rotate(12deg) brightness(1.02) contrast(1.08); }
.bench-stage[data-grade="bleach"] img { filter: saturate(0.35) contrast(1.25) brightness(1.06); }

.bench-stage img {
  transition: filter 220ms ease;
}

/* ------------------------------------------------------------ construction */

.bench-guides {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 200ms ease;
  pointer-events: none;
}

.bench[data-guides="on"] .bench-guides {
  opacity: 1;
}

.bench-mark {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

.bench-mark img {
  width: 42%;
  height: auto;
  object-fit: contain;
}

/* ----------------------------------------------------------- reduced motion */

/*
 * These are driven by the visitor, not by a timer, so there is nothing here that moves on
 * its own to switch off. Only the incidental easing goes.
 */
@media (prefers-reduced-motion: reduce) {
  .bench-stage img,
  .bench-guides {
    transition: none;
  }
}

/*
 * The two canvas instruments.
 *
 * A canvas has no intrinsic size worth having, so the stage keeps its 16/9 box and the
 * canvas fills it; the script re-measures in device pixels on every resize, which is what
 * keeps the lines crisp on a high-density screen instead of soft.
 */
.game-hud {
  position: absolute;
  inset: 0.65rem 0.75rem auto;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  pointer-events: none;
  z-index: 2;
}
.game-scores, .game-panel, .game-pause {
  color: #fff4d6;
  background: rgba(29, 18, 5, 0.92);
  border: 1px solid #e6a83c;
  border-radius: 0.5rem;
}
.game-scores { padding: 0.4rem 0.65rem; font-size: 0.75rem; }
.game-scores small { display: block; margin-top: 0.2rem; font-size: 0.65rem; }
.game-scores b { color: #ffd36a; }
.game-pause {
  width: 2.5rem;
  height: 2.5rem;
  padding: 0.5rem;
  pointer-events: auto;
  cursor: pointer;
}
.game-pause svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 3; }
.game-overlay {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  place-items: center;
  background: rgba(1, 8, 15, 0.3);
  padding: 0.75rem;
}
.game-overlay[hidden], .game-pause[hidden], [data-game-result][hidden] { display: none; }
.game-panel { text-align: center; padding: clamp(0.75rem, 2vw, 1.5rem); max-width: 100%; }
.game-panel h4 { margin: 0; color: #ffe3a0; font-size: clamp(0.9rem, 1.5vw, 1.3rem); }
.game-panel p { margin: 0.65rem 0; font-size: 0.75rem; line-height: 1.5; }
.game-action {
  font: inherit;
  font-size: 0.8rem;
  color: #fff5dc;
  background: #684412;
  border: 1px solid #f0bd55;
  border-radius: 2rem;
  padding: 0.65rem 1.2rem;
  cursor: pointer;
}
.game-action:hover, .game-pause:hover { background: #8a5b18; }
.game-action:focus-visible, .game-pause:focus-visible { outline: 2px solid white; outline-offset: 3px; }
.game-hint-phone { display: none; }
@media (max-width: 56.249em) {
  .game-hint-desktop { display: none; }
  .game-hint-phone { display: inline; }
  .game-hud { inset: 0.45rem 0.5rem auto; }
}
.bench-stage--canvas {
  background: #ffffff;
}

[data-bench="model"] .bench-stage--canvas {
  background: #07141b;
}

.bench-stage--canvas canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: manipulation;
}

[data-bench="model"] .bench-stage--canvas canvas {
  touch-action: none;           /* drag and pinch belong to the model, not the carousel */
}

.bench-stage--canvas canvas:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.bench-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.75rem;
}

.bench-scrub-label {
  flex: 1 1 8rem;
  min-width: 6rem;
}

/* The reveal instrument's range is positioned over its stage; this one is an ordinary
   control in a row, so it must not inherit that. */
.bench-range--inline {
  position: static;
  width: 100%;
  height: auto;
  opacity: 1;
}

.bench-readout {
  font-size: 0.85rem;
  color: var(--muted-color);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/*
 * The media instruments.
 *
 * A <video> keeps the 16/9 stage; an <audio> element has a fixed height of its own and no
 * business being stretched to a 16/9 box, so that stage collapses to the control bar and
 * sits on the sheet rather than on the dark stage ground.
 */
.bench-stage--media video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #0b0e13;
}

/* Keeps the 16/9 box every other instrument has, rather than collapsing to the height of
   a control bar - the row of instruments has to stay one size down the page. The player
   sits in the middle of it. */
.bench-stage--audio {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: var(--panel-bg);
}

.bench-stage--audio audio {
  width: 100%;
  max-width: 26rem;
}

/* The gallery track is this instrument's stage, so it takes the same 16/9 box; its
   controls sit under it exactly as the other instruments' controls do. */
.gallery--bench .gallery-track {
  aspect-ratio: 16 / 9;
}

.gallery--bench .gallery-slide img {
  height: 100%;
  object-fit: cover;
}

/*
 * Minimum size for the instrument controls.
 *
 * .bench-button had no rule of its own, so every one of these was a bare user-agent
 * button: 13px type in 1px of padding, which measures 23x21 on a phone. WCAG 2.2
 * SC 2.5.8 sets 24x24 as the floor, and Apple and Google both ask for 44 on touch.
 *
 * The floor is raised for everyone and raised further only where the pointer is coarse,
 * so a mouse keeps the compact controls the instruments were designed around and a
 * finger gets something it can actually hit. Only the box grows - type, border and
 * colour are untouched, so nothing about these controls looks different on a desktop.
 */
.bench-button {
  min-width: 24px;
  min-height: 24px;
}

/* A range input is 16px tall by default, which is a 16px-tall target on a timeline
   somebody is trying to scrub with a fingertip. Height here grows the control box and
   its hit area; the track and thumb are drawn centred inside it and keep their size. */
.transport-scrub {
  min-height: 24px;
}

@media (pointer: coarse) {
  .bench-button {
    min-width: 44px;
    min-height: 44px;
  }

  .transport-scrub {
    min-height: 44px;
  }
}

/* The playlist: numbered buttons, not a list of filenames. */
.bench-playlist {
  display: flex;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.bench-playlist .bench-button[aria-current="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #ffffff;
}

/* The gallery component was built for the full width of a reading column; inside an
   instrument it takes the instrument's measure instead. */
.gallery--bench {
  margin: 0;
}

.bench-stage--chat {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 0.3rem;
  padding: 0.42rem;
  background: #06131b;
}

.chat-scenarios {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.22rem;
}

.chat-scenarios button,
.chat-insights-heading button {
  min-height: 1.3rem;
  padding: 0.15rem 0.3rem;
  border: 1px solid var(--border-color);
  border-radius: 0.25rem;
  color: #b8c7cf;
  background: rgba(3, 15, 23, 0.94);
  font: inherit;
  font-size: 0.5rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: pointer;
}

.chat-scenarios button[aria-pressed="true"] {
  border-color: #8deaff;
  color: #041019;
  background: #8deaff;
}

.chat-scenarios button:focus-visible,
.chat-insights-heading button:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

.chat-workspace {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(8.5rem, 1fr);
  min-height: 0;
  overflow: hidden;
  border: 1px solid var(--border-color);
  border-radius: 0.4rem;
}

.chat-conversation {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  min-width: 0;
  min-height: 0;
  background: #f5f8fa;
}

.chat-log {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0.35rem 0.45rem;
  font: 0.58rem/1.35 sans-serif;
}

.chat-line {
  width: fit-content;
  max-width: 88%;
  margin: 0 0 0.32rem;
  padding: 0.3rem 0.4rem;
  border-radius: 0.5rem 0.5rem 0.5rem 0.12rem;
  color: #14212a;
  background: #e4eaee;
}

.chat-line b {
  display: block;
  margin-bottom: 0.08rem;
  color: #27617e;
  font-size: 0.42rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.chat-line--you { margin-left: auto; border-radius: 0.5rem 0.5rem 0.12rem; color: #07131a; background: #9cecff; }
.chat-line--you b { color: #154c64; }

.chat-line.is-pending {
  opacity: 0.55;
  font-style: italic;
}

.chat-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.25rem;
  padding: 0.3rem;
  border-top: 1px solid #cbd5db;
  background: #e9eef1;
}

.chat-input {
  min-width: 0;
  padding: 0.3rem 0.4rem;
  color: #10151c;
  background: #ffffff;
  border: 1px solid #8c9aa3;
  border-radius: 4px;
  font: 0.52rem/1.2 sans-serif;
}

.chat-form .bench-button { min-height: 1.55rem; padding: 0.2rem 0.55rem; font-size: 0.5rem; }

.chat-insights {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-width: 0;
  min-height: 0;
  padding: 0.38rem;
  color: #dbe9ef;
  background: linear-gradient(155deg, #091b25, #07131a);
}

.chat-insights-heading { display: flex; align-items: center; justify-content: space-between; gap: 0.25rem; color: #8deaff; font-size: 0.58rem; text-transform: uppercase; }
.chat-insights-heading button { min-height: 1.1rem; font-size: 0.42rem; }
.chat-insights dl { display: grid; align-content: center; gap: 0.16rem; margin: 0.2rem 0; min-height: 0; }
.chat-insights dl div { display: grid; grid-template-columns: 3.1rem minmax(0, 1fr); gap: 0.25rem; padding: 0.12rem 0; border-bottom: 1px solid rgba(111, 166, 190, 0.16); }
.chat-insights dt { color: #83949d; font-size: 0.39rem; text-transform: uppercase; }
.chat-insights dd { min-width: 0; margin: 0; overflow: hidden; color: #d5e0e5; font: 0.43rem/1.25 sans-serif; text-overflow: ellipsis; white-space: nowrap; }
.chat-insights dl div.is-found dd { color: #8deaff; }
.chat-outcome { display: flex; justify-content: space-between; gap: 0.35rem; padding: 0.25rem 0.35rem; border: 1px solid #3f687b; border-radius: 0.3rem; color: #8e9ea7; font-size: 0.42rem; text-transform: uppercase; }
.chat-outcome strong { color: #d9e8ee; text-align: right; }
.chat-outcome[data-state="complete"] { border-color: #56d8a0; }
.chat-outcome[data-state="complete"] strong { color: #78f0b7; }
.chat-outcome[data-state="pending"] strong { color: #ffd277; }

@media (min-width: 56.25em) {
  [data-bench="chat"] .chat-log { padding: 0.65rem; font-size: 1rem; line-height: 1.5; }
  [data-bench="chat"] .chat-line { padding: 0.55rem 0.65rem; overflow-wrap: anywhere; }
  [data-bench="chat"] .chat-line b { font-size: 0.75rem; }
  [data-bench="chat"] .chat-input { font-size: 1rem; padding: 0.55rem; }
  [data-bench="chat"] .chat-form .bench-button { font-size: 0.85rem; min-height: 2.5rem; }
  [data-bench="chat"] .chat-scenarios button { font-size: 0.75rem; min-height: 2.25rem; }
  [data-bench="chat"] .chat-insights { padding: 0.65rem; }
  [data-bench="chat"] .chat-insights-heading { font-size: 0.8rem; flex-wrap: wrap; }
  [data-bench="chat"] .chat-insights-heading button { font-size: 0.75rem; min-height: 2rem; }
  [data-bench="chat"] .chat-insights dl { overflow-y: auto; gap: 0.5rem; }
  [data-bench="chat"] .chat-insights dl div { grid-template-columns: minmax(0, 1fr); gap: 0.2rem; padding: 0.3rem 0; }
  [data-bench="chat"] .chat-insights dt { color: #b6c8d2; font-size: 0.75rem; }
  [data-bench="chat"] .chat-insights dd { font-size: 0.95rem; line-height: 1.4; white-space: normal; overflow-wrap: anywhere; }
  [data-bench="chat"] .chat-outcome { font-size: 0.75rem; flex-wrap: wrap; }
}

@media (max-width: 56.249em) {
  [data-bench="chat"] .bench-stage--chat { height: clamp(9.8rem, 45vw, 10.7rem); }
  .chat-scenarios button { min-height: 1.05rem; font-size: 0.42rem; }
  .chat-workspace { grid-template-columns: minmax(0, 1.5fr) minmax(6.4rem, 1fr); }
  .chat-log { padding: 0.25rem; font-size: 0.5rem; }
  .chat-line { max-width: 94%; padding: 0.22rem 0.28rem; margin-bottom: 0.2rem; }
  .chat-line b { font-size: 0.34rem; }
  .chat-form { padding: 0.22rem; gap: 0.18rem; }
  .chat-input { padding: 0.22rem 0.28rem; font-size: 0.45rem; }
  .chat-form .bench-button { min-height: 1.25rem; padding: 0.1rem 0.35rem; font-size: 0.42rem; }
  .chat-insights { padding: 0.25rem; }
  .chat-insights-heading { font-size: 0.45rem; }
  .chat-insights-heading button { min-height: 0.9rem; padding: 0.05rem 0.2rem; font-size: 0.34rem; }
  .chat-insights dl { gap: 0.05rem; margin: 0.1rem 0; }
  .chat-insights dl div { display: block; padding: 0.05rem 0; }
  .chat-insights dt { font-size: 0.3rem; }
  .chat-insights dd { font-size: 0.35rem; }
  .chat-outcome { display: block; padding: 0.14rem 0.2rem; font-size: 0.32rem; }
  .chat-outcome strong { display: block; text-align: left; }
}

.chat-input:focus-visible,
.chat-log:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/*
 * The app instrument.
 *
 * A tab strip over a panel, sized so the calculator fills the same 16/9 box every other
 * instrument keeps. The keypad is a four-column grid rather than flex, so the wide keys
 * span cleanly and every key lands on the same rhythm.
 */
.bench-stage--app {
  display: flex;
  flex-direction: column;
  background: var(--panel-bg);
  padding: 0.5rem;
  gap: 0.4rem;
}

.bench-tabs {
  display: flex;
  gap: 0.3rem;
  flex: none;
}

.bench-tab {
  padding: 0.25rem 0.7rem;
  font: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-color);
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
}

.bench-tab[aria-selected="true"] {
  color: var(--accent);
  border-color: var(--border-color);
  background: #ffffff;
}

.bench-tab[data-app-pick][aria-selected="true"] {
  color: #05070b;
}

.bench-app {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.bench-app[hidden] {
  display: none;
}

.calc-display {
  flex: none;
  padding: 0.35rem 0.6rem;
  background: #ffffff;
  border: 1px solid var(--border-color);
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
  font-size: clamp(1rem, 3.5cqi, 1.5rem);
  text-align: right;
  overflow: hidden;
  white-space: nowrap;
}

.calc-keys {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.3rem;
}

.bench-key {
  font: inherit;
  font-size: 0.95rem;
  color: var(--text-color);
  background: #ffffff;
  border: 1px solid var(--border-color);
  border-radius: 4px;
  cursor: pointer;
}

.bench-key:hover {
  border-color: var(--accent);
}

.bench-key:active {
  background: var(--panel-bg);
}

.bench-key--op {
  color: var(--accent);
  font-weight: 600;
}

.bench-key--wide {
  grid-column: span 2;
}

.bench-key:focus-visible,
.bench-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}


/*
 * The transport bar.
 *
 * Laid out the way a video player is, because that is the thing everyone already knows
 * how to operate: a small round play button, the scrub line taking whatever width is
 * left, then the counter and the frame steppers. The old version was a row of equal
 * buttons, which made 'play' look like just another one of them.
 */
.bench-gaits {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  z-index: 2;
  display: flex;
  gap: 0.3rem;
  margin: 0;
}

.bench-gaits .bench-tab {
  color: #05070b;
  border-color: transparent;
  background: transparent;
}

.bench-gaits .bench-tab[aria-pressed="true"] {
  color: #05070b;
  border-color: rgba(5, 7, 11, 0.7);
  background: transparent;
}

.bench-transport {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-top: 0.5rem;
}

.transport-play {
  order: 2;
  flex: none;
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  border: 1px solid var(--border-color);
  border-radius: 50%;
  background: #ffffff;
  color: var(--accent);
  cursor: pointer;
}

.transport-play svg {
  width: 0.8rem;
  height: 0.8rem;
  fill: currentColor;
  pointer-events: none;
  grid-area: 1 / 1;
}

/* One icon per state, chosen by the button's own attribute rather than by the script
   swapping markup - the script sets one value and the stylesheet does the rest. */
.transport-play[data-state="paused"] .icon-pause,
.transport-play[data-state="playing"] .icon-play {
  display: none;
}

.transport-play:hover {
  border-color: var(--accent);
}

/*
 * The scrub line. Reset from .bench-range, which is absolutely positioned over a stage
 * for the reveal instrument and would otherwise drag that behaviour in here.
 */
.transport-scrub {
  order: 4;
  position: static;
  flex: 1;
  min-width: 0;
  height: auto;
  opacity: 1;
  accent-color: var(--accent);
}

.transport-time {
  order: 5;
  flex: none;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted-color);
}

.transport-step {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.8rem;
  height: 1.8rem;
  padding: 0;
  font: inherit;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--muted-color);
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
}

.transport-step[data-walk-prev] {
  order: 1;
}

.transport-step[data-walk-next] {
  order: 3;
  margin-right: 0.2rem;
}

.transport-step:hover {
  color: var(--accent);
  border-color: var(--border-color);
}

.transport-play:focus-visible,
.transport-step:focus-visible,
.transport-scrub:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The clock app. */
.clock-face {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(0.4rem, 1.8cqi, 0.85rem);
  padding: clamp(0.75rem, 3cqi, 1.5rem);
  background: #ffffff;
  border: 1px solid var(--border-color);
  border-radius: 4px;
}

.clock-time {
  font-size: clamp(2.5rem, 14cqi, 5rem);
  font-weight: 600;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--text-color);
  line-height: 1.1;
}

.clock-date {
  margin: 0;
  font-size: clamp(0.9rem, 3.4cqi, 1.45rem);
  line-height: 1.2;
  text-align: center;
  color: var(--muted-color);
}

.clock-zone {
  margin: 0;
  font-size: clamp(0.78rem, 2.6cqi, 1.1rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-color);
  opacity: 0.8;
}

.clock-controls {
  flex: none;
  display: flex;
  justify-content: flex-end;
}

/*
 * The route out of an instrument.
 *
 * Sat in the gutter to the right of the instrument rather than under it, so it never
 * interrupts the run of the page. The instrument is capped at 32rem inside a 72ch column,
 * which leaves roughly a third of the measure empty on the right - this is what that space
 * is for.
 *
 * Below 52em there is no gutter left to sit in, so it drops to the top-right corner of the
 * instrument instead of overlapping the text or forcing the page sideways.
 */
.bench {
  position: relative;
}

.bench-link {
  position: absolute;
  top: 50%;
  left: calc(100% + 1.5rem);
  translate: 0 -50%;

  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;

  color: var(--muted-color);
  border: 1px solid var(--border-color);
  border-radius: 50%;
  background: #ffffff;
  transition: color 160ms ease, border-color 160ms ease, transform 160ms ease;
}

.bench-link svg {
  width: 1.35rem;
  height: 1.35rem;
  fill: currentColor;
  pointer-events: none;
}

.bench-link:hover,
.bench-link:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
  transform: scale(1.08);
}

.bench-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

@media (max-width: 52em) {
  .bench-link {
    top: 0;
    left: auto;
    right: 0;
    translate: none;
    width: 2.25rem;
    height: 2.25rem;
  }

  .bench-link svg {
    width: 1.1rem;
    height: 1.1rem;
  }
}

/* --- Web design: the responsive frame ------------------------------------------- */

.bench-stage--frame {
  display: grid;
  place-items: center;
  background: var(--panel-bg);
  padding: 0.6rem;
  overflow: hidden;
}

/*
 * Two boxes, not one.
 *
 * The frame keeps its true pixel width - 1100px really is 1100px, which is the only way
 * the layout inside is the layout a desktop would get. It is then scaled from its top-left
 * corner, and the shell around it is sized to the SCALED result.
 *
 * That split is the whole fix. A transform does not change an element's layout box, so a
 * 1100px frame stayed 1100px as far as the grid was concerned: it could not be centred
 * inside a 512px stage, fell back to start alignment, and the visible box ended up pushed
 * hundreds of pixels off to one side. Giving the shell the scaled dimensions means the
 * thing being centred is the thing you can see.
 */
.mini-shell {
  overflow: hidden;
  border-radius: 6px;
  border: 1px solid var(--border-color);
  background: #ffffff;
}

.mini-frame {
  width: 1100px;
  max-width: none;
  transform-origin: top left;
  transform: scale(var(--fit, 0.42));
  background: #ffffff;

  /* This is the whole point: the miniature page inside asks how wide THIS is. */
  container-type: inline-size;
}

.mini-bar {
  display: flex;
  gap: 5px;
  padding: 7px 9px;
  background: #e9eef3;
  border-bottom: 1px solid var(--border-color);
}

.mini-bar i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #c3ccd6;
}

.mini-page { padding: 16px; }

.mini-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.mini-head b { font-size: 20px; color: var(--accent); letter-spacing: 0.06em; }
.mini-nav { display: flex; gap: 10px; }
.mini-nav span { width: 42px; height: 8px; border-radius: 3px; background: #d7dee6; }

.mini-hero {
  height: 150px;
  border-radius: 6px;
  background: linear-gradient(120deg, #cfe0ee, #9dc3de);
  margin-bottom: 14px;
}

.mini-grid { display: grid; gap: 12px; grid-template-columns: repeat(3, 1fr); }
.mini-grid div { height: 78px; border-radius: 6px; background: #e6ecf2; }

/* Container queries, not media queries. */
@container (max-width: 820px) {
  .mini-grid { grid-template-columns: repeat(2, 1fr); }
  .mini-hero { height: 118px; }
}

@container (max-width: 480px) {
  .mini-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .mini-nav span { width: 30px; }
  .mini-grid { grid-template-columns: 1fr; }
  .mini-hero { height: 92px; }
}

/* --- AI workflow automation ------------------------------------------------------ */

.bench-stage--workflow {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 0.5rem;
  padding: 0.7rem;
  background:
    linear-gradient(rgba(1, 18, 27, 0.94), rgba(1, 12, 19, 0.96)),
    repeating-linear-gradient(90deg, transparent 0 39px, rgba(123, 211, 255, 0.08) 40px),
    repeating-linear-gradient(0deg, transparent 0 39px, rgba(123, 211, 255, 0.08) 40px);
}

.workflow-path {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: center;
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.workflow-path li {
  position: relative;
  min-width: 0;
  min-height: 3.25rem;
  border: 1px solid rgba(111, 199, 239, 0.32);
  border-radius: 0.55rem;
  color: #8b9aa3;
  background: rgba(3, 15, 23, 0.86);
  transition: border-color 180ms ease, box-shadow 180ms ease, color 180ms ease;
}

.workflow-path button {
  display: grid;
  place-items: center;
  align-content: center;
  width: 100%;
  min-height: 3.15rem;
  padding: 0.25rem;
  border: 0;
  color: inherit;
  background: transparent;
  font: inherit;
}

.workflow-path button:enabled { cursor: pointer; }
.workflow-path button:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }

.workflow-path li:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 100%;
  width: 1.25rem;
  height: 1px;
  background: rgba(111, 199, 239, 0.4);
}

.workflow-path li:not(:last-child)::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: calc(50% - 0.18rem);
  left: calc(100% + 0.85rem);
  width: 0.35rem;
  height: 0.35rem;
  border-top: 1px solid rgba(111, 199, 239, 0.7);
  border-right: 1px solid rgba(111, 199, 239, 0.7);
  transform: rotate(45deg);
}

.workflow-step-icon {
  display: grid;
  place-items: center;
  width: 1.45rem;
  height: 1.45rem;
  margin-bottom: 0.28rem;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: 0.62rem;
}

.workflow-path b { color: inherit; font-size: 0.72rem; font-weight: 600; }
.workflow-path small { overflow: hidden; max-width: 100%; color: inherit; font-size: 0.55rem; text-overflow: ellipsis; white-space: nowrap; }
.workflow-path li.is-running { color: #a8e6ff; border-color: #86dcff; box-shadow: 0 0 1rem rgba(95, 205, 255, 0.55); }
.workflow-path li.is-complete { color: #71e3a8; border-color: rgba(113, 227, 168, 0.8); }
.workflow-path li.is-current { color: #d9f4ff; border-color: #86dcff; }

.workflow-inspector {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  min-height: 0;
  overflow: hidden;
  border: 1px solid rgba(111, 199, 239, 0.28);
  border-radius: 0.45rem;
  background: rgba(0, 7, 12, 0.72);
}

.workflow-input,
.workflow-artifact {
  box-sizing: border-box;
  height: 100%;
  min-width: 0;
  min-height: 0;
  padding: 0.55rem 0.65rem;
}

.workflow-input { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 0.25rem; }
.workflow-input label,
.workflow-artifact h4 { margin: 0; color: var(--accent); font-size: 0.65rem; letter-spacing: 0.05em; text-transform: uppercase; }
.workflow-input textarea,
.workflow-reply {
  box-sizing: border-box;
  width: 100%;
  min-height: 0;
  resize: none;
  border: 1px solid rgba(111, 199, 239, 0.32);
  border-radius: 0.3rem;
  padding: 0.45rem;
  color: #dcecf3;
  background: #07141d;
  font: inherit;
  font-size: 0.65rem;
  line-height: 1.35;
}
.workflow-artifact { overflow: auto; border-left: 1px solid rgba(111, 199, 239, 0.28); color: #dcecf3; font-size: 0.62rem; }
.workflow-artifact h4 { margin-bottom: 0.4rem; }
.workflow-artifact p { margin: 0; line-height: 1.45; white-space: pre-wrap; }
.workflow-data { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.25rem 0.7rem; margin: 0; }
.workflow-data div { display: grid; grid-template-columns: minmax(4.3rem, auto) 1fr; gap: 0.35rem; border-bottom: 1px solid rgba(111, 199, 239, 0.13); padding-bottom: 0.16rem; }
.workflow-data dt { color: #86dcff; }
.workflow-data dd { min-width: 0; margin: 0; overflow-wrap: anywhere; }
.workflow-data .is-missing dd { color: #ffd76b; }
.workflow-reply { display: block; height: calc(100% - 1.5rem); }

.workflow-controls {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.workflow-controls .bench-button {
  display: grid;
  place-items: center;
  min-height: 2rem;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--border-color);
  border-radius: 999px;
  color: #dcecf3;
  background: rgba(3, 15, 23, 0.86);
  font: inherit;
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.workflow-controls .bench-button:not(:disabled):hover,
.workflow-controls .bench-button:not(:disabled):focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0.75rem rgba(95, 205, 255, 0.35);
  color: #ffffff;
}

.workflow-controls .bench-button:disabled { cursor: not-allowed; opacity: 0.42; }

/* --- Social media campaign preview ---------------------------------------------- */

.bench-stage--social {
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: 0.35rem;
  background:
    radial-gradient(circle at 20% 18%, rgba(95, 205, 255, 0.14), transparent 38%),
    #06131b;
}

.social-preview {
  --social-surface: #ffffff;
  --social-ink: #11161b;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto auto;
  width: min(82%, 25rem);
  height: 100%;
  min-height: 0;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.72);
  border-radius: 0.55rem;
  color: var(--social-ink);
  background: var(--social-surface);
  box-shadow: 0 0.7rem 2rem rgba(0, 0, 0, 0.35);
}

.social-preview-bar,
.social-account,
.social-engagement {
  display: flex;
  align-items: center;
}

.social-preview-bar {
  min-height: 1.25rem;
  gap: 0.35rem;
  padding: 0.18rem 0.45rem;
  border-bottom: 1px solid #d7dde1;
  font-size: 0.5rem;
  font-weight: 700;
}

.social-platform-mark {
  display: grid;
  place-items: center;
  width: 1rem;
  height: 1rem;
  border-radius: 0.25rem;
  color: #fff;
  background: #111;
  font-size: 0.38rem;
}

.social-preview-menu,
.social-save { margin-left: auto; }

.social-account {
  gap: 0.35rem;
  min-height: 1.55rem;
  padding: 0.2rem 0.45rem;
  font-size: 0.45rem;
}

.social-account > span:nth-child(2) { display: grid; }
.social-account small { color: #68727a; font-size: 0.38rem; }
.social-avatar {
  display: grid;
  place-items: center;
  width: 1.1rem;
  height: 1.1rem;
  flex: 0 0 auto;
  border-radius: 50%;
  color: #051019;
  background: linear-gradient(135deg, #9bf0ff, #5fcdff 52%, #8b6cff);
  font-size: 0.36rem;
  font-weight: 900;
}

.social-follow {
  margin-left: auto;
  padding: 0.16rem 0.42rem;
  border: 0;
  border-radius: 1rem;
  color: #fff;
  background: #1577e8;
  font: inherit;
  font-size: 0.4rem;
}

.social-art {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 0;
  overflow: hidden;
  padding: 0.65rem;
  color: #f4fcff;
  isolation: isolate;
  background:
    linear-gradient(145deg, transparent 0 42%, rgba(69, 218, 255, 0.18) 42% 43%, transparent 43%),
    radial-gradient(circle at 68% 28%, #42d8ff 0 2%, transparent 2.5%),
    linear-gradient(145deg, #061019 15%, #0b3542 64%, #111e2c);
}

.social-art::before,
.social-art::after {
  content: "";
  position: absolute;
  z-index: -1;
  border: 1px solid rgba(134, 232, 255, 0.45);
  transform: rotate(24deg);
}

.social-art::before { width: 58%; aspect-ratio: 1; top: -35%; right: -4%; }
.social-art::after { width: 32%; aspect-ratio: 1; top: 14%; right: 16%; }
.social-art-orbit {
  position: absolute;
  z-index: -1;
  top: 10%;
  right: 13%;
  width: 37%;
  aspect-ratio: 1;
  border: 0.22rem solid rgba(4, 14, 22, 0.62);
  border-radius: 50%;
  box-shadow: 0 0 0 0.12rem rgba(135, 234, 255, 0.72), 0 0 1rem rgba(95, 205, 255, 0.55);
}

.social-art-kicker,
.social-art-copy,
.social-art-cta { font-size: 0.42rem; }
.social-art-kicker { color: #8deaff; letter-spacing: 0.16em; text-transform: uppercase; }
.social-art strong { max-width: 76%; font-size: clamp(0.85rem, 2.2vw, 1.35rem); line-height: 0.95; text-transform: uppercase; }
.social-art-copy { max-width: 72%; margin-top: 0.18rem; color: #d8edf5; }
.social-art-cta {
  align-self: flex-start;
  margin-top: 0.35rem;
  padding: 0.18rem 0.4rem;
  border: 1px solid currentColor;
  border-radius: 1rem;
}

.social-preview[data-campaign="1"] .social-art {
  background: radial-gradient(circle at 78% 24%, #ffc66d 0 3%, transparent 3.5%), linear-gradient(145deg, #1c0b08, #8d351d 58%, #ffb24d);
}
.social-preview[data-campaign="1"] .social-art-kicker { color: #ffd58f; }
.social-preview[data-campaign="2"] .social-art {
  background: radial-gradient(circle at 72% 22%, #d9b9ff 0 3%, transparent 3.5%), linear-gradient(145deg, #100921, #4f2381 58%, #d252d9);
}
.social-preview[data-campaign="2"] .social-art-kicker { color: #efd8ff; }

.social-engagement { gap: 0.5rem; min-height: 1rem; padding: 0.08rem 0.45rem; font: 700 0.72rem/1 sans-serif; }
.social-caption { margin: 0; padding: 0.05rem 0.45rem 0.25rem; font: 0.39rem/1.25 sans-serif; }

.social-preview[data-format="story"],
.social-preview[data-format="reel"] { width: min(46%, 13rem); }
.social-preview[data-format="story"] .social-caption,
.social-preview[data-format="story"] .social-engagement,
.social-preview[data-format="reel"] .social-caption { display: none; }
.social-preview[data-format="reel"] .social-engagement { position: absolute; right: 0.35rem; bottom: 0.35rem; z-index: 2; color: #fff; flex-direction: column; }
.social-preview[data-format="advertisement"] { width: min(94%, 30rem); }
.social-preview[data-format="advertisement"] .social-art { padding-inline: 1rem; }
.social-preview[data-platform="tiktok"],
.social-preview[data-platform="x"] { --social-surface: #080b0e; --social-ink: #f5f7f8; }
.social-preview[data-platform="tiktok"] .social-preview-bar,
.social-preview[data-platform="x"] .social-preview-bar { border-color: #343b40; }
.social-preview[data-platform="youtube"] .social-art { order: 1; }

.social-controls { display: grid; gap: 0.28rem; margin-top: 0.38rem; }
.social-control-row { display: grid; gap: 0.2rem; }
.social-platforms { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.social-formats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.social-control,
.social-campaign-arrow {
  min-width: 0;
  min-height: 1.25rem;
  padding: 0.16rem 0.22rem;
  border: 1px solid var(--border-color);
  border-radius: 0.25rem;
  color: var(--muted-color);
  background: rgba(2, 13, 20, 0.84);
  font: inherit;
  font-size: 0.46rem;
  text-transform: uppercase;
  cursor: pointer;
}
.social-control[aria-pressed="true"] { color: #041019; background: #8deaff; border-color: #8deaff; }
.social-control:hover,
.social-control:focus-visible,
.social-campaign-arrow:hover,
.social-campaign-arrow:focus-visible { color: #fff; border-color: #8deaff; outline: none; }
.social-campaign-nav { display: grid; grid-template-columns: 1.35rem minmax(0, auto) 1.35rem; align-items: center; justify-content: center; gap: 0.5rem; }
.social-campaign-arrow { padding: 0; font-size: 1rem; line-height: 1; }
.social-campaign-nav .bench-readout { text-align: center; white-space: nowrap; }

@media (max-width: 56.249em) {
  .social-preview { width: min(84%, 22rem); }
  .social-preview[data-format="story"], .social-preview[data-format="reel"] { width: min(52%, 12rem); }
  .social-preview[data-format="advertisement"] { width: 96%; }
  .social-platforms { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .social-control { min-height: 1.05rem; padding: 0.1rem; font-size: 0.41rem; }
  .social-controls { gap: 0.18rem; margin-top: 0.25rem; }
  .social-preview-bar { min-height: 1rem; }
  .social-account { min-height: 1.25rem; }
  .social-caption { display: none; }
  .social-art { padding: 0.4rem; }
  .social-art strong { font-size: 0.72rem; }
  .social-art-copy { font-size: 0.36rem; }
  .social-art-cta { margin-top: 0.2rem; font-size: 0.36rem; }
}

/* --- The analogue face ------------------------------------------------------------ */

/*
 * One face is shown at a time, chosen by an attribute on the container rather than by the
 * script hiding and showing elements itself. The script sets one value; everything else
 * follows from the stylesheet, which keeps the two faces from drifting apart.
 */
.clock-face[data-clock-mode="digital"] .dial { display: none; }

/*
 * In analogue mode the dial is the whole app: the digital readout, the date and the
 * timezone all step aside so the face can take the height instead of sharing it with
 * three lines of text it already implies.
 */
.clock-face[data-clock-mode="analogue"] .clock-time,
.clock-face[data-clock-mode="analogue"] .clock-date,
.clock-face[data-clock-mode="analogue"] .clock-zone { display: none; }

.clock-face[data-clock-mode="analogue"] { padding: 0.35rem; }

/*
 * Sized from the height it has, not from a guessed rem value. The stage is a fixed 16/9
 * box, so height is always the scarce dimension for a circle - taking 100% of it and
 * letting aspect-ratio derive the width means the face fills the instrument at any size
 * without ever being the thing that overflows it.
 */
.dial {
  height: 100%;
  width: auto;
  max-width: 100%;
  aspect-ratio: 1;
  overflow: visible;
}

.dial-rim {
  fill: #ffffff;
  stroke: var(--border-color);
  stroke-width: 1.2;
}

/* Sixty of them, so there is something to read a minute against. */
.dial-tick {
  stroke: var(--border-color);
  stroke-width: 0.7;
}

.dial-tick--hour {
  stroke: var(--muted-color);
  stroke-width: 2.2;
  stroke-linecap: round;
}

.dial-hand {
  stroke: var(--text-color);

  /*
   * No transform-origin here, deliberately.
   *
   * The hands are rotated by the presentation attribute rotate(angle 50 50), which already
   * names the pivot. Declaring transform-origin as well applies the offset a second time,
   * and the hands swing out of the dial and across the panel. One or the other - never
   * both - and the attribute is the one that keeps the pivot next to the angle that uses
   * it.
   */
}

/*
 * The hour hand is short and blunt, the minute hand long and fine. That contrast - not
 * the stroke width alone - is what lets the time be read at a glance; at 4 against 2.8
 * the two were near enough identical that the face was unreadable.
 *
 * Square caps rather than round: a round cap on a thick stroke adds half its width to
 * each end, which blunted the hour hand into a sausage and pushed the tails past the pin.
 */
.dial-hand--hour {
  stroke-width: 3.6;
  stroke-linecap: butt;
}

.dial-hand--minute {
  stroke-width: 1.9;
  stroke-linecap: butt;
}

/* The second hand is the only part that moves visibly, so it is the only part that gets
   the accent - it reads as the live element rather than as decoration. */
.dial-hand--second {
  stroke: var(--accent);
  stroke-width: 0.9;
  stroke-linecap: round;
}

.dial-pin { fill: var(--accent); }

/*
 * Illustration plates.
 *
 * The instruments all share one 16/9 stage, and these pages are portrait - roughly the
 * proportions of a comic page. Cropping them to fill the stage, which is what every other
 * gallery here does, would show a horizontal band out of the middle of each drawing and
 * throw away most of the art.
 *
 * So the box keeps its size and the page is fitted inside it instead, sitting on a panel.
 * A drawing that has been cropped is no longer the drawing; empty space beside it costs
 * nothing.
 */
.gallery--plates .gallery-slide img {
  /* The element takes the stage's box; the drawing is fitted inside it. Without
     aspect-ratio: auto the intrinsic portrait ratio drives the layout instead and the
     image grows taller than the instrument it sits in. */
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  object-fit: contain;
  background: var(--panel-bg);
}

/* Desktop Services cards are height-led. The carousel owns a finite row between the
   page introduction and its navigation, so the interactive stage consumes the space
   left after the title, description and controls instead of deriving an oversized
   height from the card width. Phone benches retain their established 16:9 layout. */
@media (min-width: 56.25em) {
  .services-page .services-carousel .bench-stage {
    width: 100%;
    height: 100%;
    min-height: 0;
    aspect-ratio: auto;
  }

  .services-page .services-carousel .gallery--bench {
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    height: auto;
    min-height: 0;
    overflow: hidden;
  }

  .services-page .services-carousel .gallery--bench .gallery-track {
    height: 100%;
    min-height: 0;
    aspect-ratio: auto;
  }

  .services-page .services-carousel .gallery--bench .gallery-controls {
    margin-top: 0.45rem;
  }
}

/* Short desktop windows use the card's visible scrollbar as the fallback. The minimum
   is derived from the available viewport height (never from card width), which leaves
   enough vertical room for dense app/workflow controls without changing phone layout. */
@media (min-width: 56.25em) and (max-height: 52rem) {
  .services-page .services-carousel [data-bench="chat"] .bench-stage,
  .services-page .services-carousel [data-bench="workflow"] .bench-stage,
  .services-page .services-carousel [data-bench="app"] .bench-stage,
  .services-page .services-carousel [data-bench="platformer"] .bench-stage,
  .services-page .services-carousel [data-bench="social"] .bench-stage {
    min-height: 38vh;
  }
}
