/*
 * Shimti Multimedia - the workbench
 *
 * Styling for the instruments on the Work page. They live inside the white sheet, so they
 * inherit its ink palette rather than the interface's glow.
 *
 * @requires assets/scripts/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%;
}

.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.
 */
.bench-stage--canvas {
  background: #ffffff;
}

.bench-stage--canvas canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: manipulation;   /* no double-tap zoom while jumping */
}

.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;
}

/*
 * The conversation instrument.
 *
 * The transcript is its own scroll container, which is what keeps a long exchange from
 * growing the stage and shoving the rest of the page down. The form is pinned under it so
 * the input never leaves the 16/9 box the other instruments keep.
 */
.bench-stage--chat {
  display: flex;
  flex-direction: column;
  background: var(--panel-bg);
  padding: 0.6rem;
  gap: 0.5rem;
}

.chat-log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0.2rem 0.35rem;
  font-size: 0.85rem;
  line-height: 1.5;
}

.chat-line {
  margin: 0 0 0.55rem;
  color: var(--text-color);
}

.chat-line b {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted-color);
  margin-bottom: 0.1rem;
}

.chat-line--you b {
  color: var(--accent);
}

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

.chat-form {
  display: flex;
  gap: 0.4rem;
  flex: none;
}

.chat-input {
  flex: 1;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  font: inherit;
  font-size: 0.85rem;
  color: var(--text-color);
  background: #ffffff;
  border: 1px solid var(--border-color);
  border-radius: 4px;
}

.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-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 {
  display: flex;
  gap: 0.3rem;
  margin-top: 0.7rem;
}

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

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

.transport-play {
  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 {
  position: static;
  flex: 1;
  min-width: 0;
  height: auto;
  opacity: 1;
  accent-color: var(--accent);
}

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

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

.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: 0.15rem;
  background: #ffffff;
  border: 1px solid var(--border-color);
  border-radius: 4px;
}

.clock-time {
  font-size: clamp(1.6rem, 11cqi, 3rem);
  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: 0.85rem;
  color: var(--muted-color);
}

.clock-zone {
  margin: 0;
  font-size: 0.72rem;
  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; }
}

/* --- Logo design: the monogram --------------------------------------------------- */

.bench-stage--mono {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  background: var(--panel-bg);
}

.mono-row { display: flex; align-items: center; gap: 1.4rem; }

.mono {
  display: grid;
  place-items: center;
  color: #ffffff;
  background: var(--accent);
  line-height: 1;
  /* The tracking is applied to the whole string, which leaves a trailing gap on the
     right and knocks the glyphs off centre; this takes it back. */
  text-indent: 0.06em;
}

.mono[data-shape="circle"] { border-radius: 50%; }
.mono[data-shape="square"] { border-radius: 12%; }
.mono[data-shape="none"] { background: none; color: var(--accent); }

.mono--lg { width: 112px; height: 112px; font-size: 34px; }
.mono--md { width: 44px; height: 44px; font-size: 14px; }
.mono--sm { width: 16px; height: 16px; font-size: 6px; }

.mono--md[data-shape="square"] { border-radius: 8px; }
.mono--sm[data-shape="square"] { border-radius: 3px; }

.mono-scale {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-color);
}

/* --- Social media: the crops ------------------------------------------------------ */

.bench-stage--formats {
  display: grid;
  place-items: center;
  background: var(--panel-bg);
  padding: 0.5rem;
}

.format-row {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
}

.format {
  margin: 0;
  text-align: center;
}

.format img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;      /* the crop itself */
  border: 1px solid var(--border-color);
  border-radius: 3px;
  background: #fff;
}

.format figcaption {
  margin-top: 0.2rem;
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-color);
}

.format[data-format="1:1"]  { width: 92px;  height: 92px; cursor: crosshair; }
.format[data-format="4:5"]  { width: 62px;  height: 78px; }
.format[data-format="9:16"] { width: 48px;  height: 85px; }
.format[data-format="16:9"] { width: 104px; height: 59px; }
.format[data-format="3:1"]  { width: 108px; height: 36px; }
.format[data-format="1:1s"] { width: 40px;  height: 40px; }
.format[data-format="1:1s"] img { border-radius: 50%; }

/* --- 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);
}
