/* Roboto (variable, weights 400-900), self-hosted: the Google Fonts files from
   fonts.gstatic.com, saved locally so no visitor IP goes to Google and the
   playback screen never blinks from a fallback font. Roboto is Apache-2.0
   licensed. Latin covers Swedish (å ä ö); latin-ext catches other diacritics in
   exercise names — the browser only downloads a file when a character needs it. */
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('../fonts/roboto-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('../fonts/roboto-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Design tokens taken from Figma (macOS/iOS UI kit) — see PLANNING.md */
:root {
  --color-label-primary: rgba(0, 0, 0, 0.85);
  --color-label-secondary: rgba(0, 0, 0, 0.5);
  --color-accent: #08f;
  --color-border: rgba(0, 0, 0, 0.08);
  --color-bg: #ffffff;
  --color-sheet-bg: #f2f2f7; /* the grey page behind the exercise editor's cards */
  --color-warning: #f43343;
  --play-label-bg: #1d1c28;
  --play-round-bg: #23222f;
  --color-cta: #f45633;
  --color-cta-hover: #e2481f;
  --radius: 6px;
  --font-sans: 'Roboto', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
}

body {
  background: var(--color-bg);
  color: var(--color-label-primary);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
}

/* Tooltip system: add `data-tooltip="..."` to any control. Pure CSS — the 1s
   delay only applies when appearing (transition-delay on the :hover rule), so
   it vanishes instantly on mouse-out instead of lingering. `data-tooltip-pos="bottom"`
   flips it below the control for anything hugging the top edge of the screen. */
[data-tooltip] {
  position: relative;
}

[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 7px);
  left: 50%;
  transform: translateX(-50%);
  background: #191925;
  color: #fff;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 510;
  line-height: 1.3;
  white-space: nowrap;
  padding: 4px 8px;
  border-radius: 5px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 100;
}

[data-tooltip]:hover::after {
  opacity: 1;
  transition-delay: 1s;
}

[data-tooltip][data-tooltip-pos='bottom']::after {
  bottom: auto;
  top: calc(100% + 7px);
}

#app {
  min-height: 100%;
  max-width: 480px;
  margin: 0 auto;
  padding: 16px;
}

/* Header: title + play button */
.workout-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.workout-title,
.workouts-title {
  flex: 1;
  min-width: 0;
  font-weight: 700;
  font-size: 22px;
  color: var(--color-label-primary);
  padding: 4px 0;
}

.workout-title {
  border: none;
  background: transparent;
  font-family: inherit;
}

.workouts-title {
  margin: 0;
}

.workout-title:focus {
  outline: none;
  box-shadow: inset 0 -2px 0 var(--color-accent);
}

/* .play-btn is the header's full-size play button; .row-play-btn is the smaller
   variant used inline in a "My Workouts" row — same shape and states, different size. */
.play-btn,
.row-play-btn {
  flex-shrink: 0;
  border-radius: 50%;
  border: none;
  background: var(--color-cta);
  color: white;
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.play-btn {
  width: 40px;
  height: 40px;
  font-size: 16px;
}

.row-play-btn {
  width: 28px;
  height: 28px;
  font-size: 11px;
}

.play-btn:hover:not(:disabled),
.row-play-btn:hover:not(:disabled) {
  background: var(--color-cta-hover);
}

.play-btn:active:not(:disabled),
.row-play-btn:active:not(:disabled) {
  transform: scale(0.92);
}

.play-btn:disabled,
.row-play-btn:disabled {
  background: rgba(0, 0, 0, 0.15);
  cursor: not-allowed;
}

/* My Workouts — the home screen */
.workouts-empty {
  color: var(--color-label-secondary);
  font-size: 14px;
  margin: 24px 0;
  text-align: center;
}

.setup-back-btn {
  display: block;
  margin-bottom: 8px;
}

.total-duration {
  color: var(--color-label-secondary);
  font-size: 13px;
  margin: 6px 0 16px;
}

/* Exercise list */
.exercise-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--color-border);
}

.exercise-row {
  border-bottom: 1px solid var(--color-border);
}

.exercise-row.dragging {
  opacity: 0.5;
}

.row-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 4px;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color 0.1s;
}

.row-summary:hover {
  background: rgba(0, 0, 0, 0.03);
}

.drag-handle {
  cursor: grab;
  touch-action: none;
  color: var(--color-label-secondary);
  padding: 4px;
  border-radius: 4px;
  transition:
    color 0.15s,
    background-color 0.15s;
}

.drag-handle:hover {
  color: var(--color-label-primary);
  background: rgba(0, 0, 0, 0.06);
}

.drag-handle:active {
  cursor: grabbing;
  background: rgba(0, 0, 0, 0.1);
}

.row-order {
  width: 18px;
  text-align: center;
  color: var(--color-label-secondary);
  font-size: 13px;
  flex-shrink: 0;
}

.row-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
}

.row-offline-flag {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  color: var(--color-label-secondary);
}

.row-duration {
  flex-shrink: 0;
  width: 36px;
  text-align: right;
  color: var(--color-label-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

/* Fixed-width slot regardless of what's inside (nothing / one thumb / a stack) —
   otherwise a row's duration figure shifts left/right depending on its neighbor,
   since it sits right after the flexible name column. */
.row-thumb {
  flex-shrink: 0;
  width: 44px;
  display: flex;
  align-items: center;
  gap: 3px;
}

.row-thumb-item {
  display: block;
  width: 32px;
  height: 32px;
  border-radius: var(--radius);
  overflow: hidden;
  object-fit: cover;
  background: rgba(0, 0, 0, 0.05);
}

/* A video reads as motion, not a pose — give it a wider, landscape thumbnail
   instead of the square used for still images. */
.row-thumb-item.video {
  width: 44px;
  height: 28px;
}

/* More than one still image: show only the first, with a second card peeking out
   behind it — reads as "there's a stack" without competing with the photo itself. */
.row-thumb-stack {
  position: relative;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
}

.row-thumb-stack::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  /* Same size as the front image (.row-thumb-item) — inset:0 on this larger
     container made the "behind" card 4px bigger on top of the offset, which read
     as a much bulkier peek than intended. */
  width: 32px;
  height: 32px;
  border-radius: var(--radius);
  background: var(--color-bg);
  border: 1px solid #000;
  transform: translate(2px, 2px);
  z-index: 0;
}

.row-thumb-stack .row-thumb-item {
  position: relative;
  z-index: 1;
}

.row-delete {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  border: none;
  background: transparent;
  color: var(--color-label-secondary);
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  transition:
    color 0.15s,
    background-color 0.15s,
    transform 0.1s;
}

.row-delete:hover {
  color: var(--color-warning);
  background: rgba(244, 51, 67, 0.08);
}

.row-delete:active {
  transform: scale(0.9);
}

/* Repeat blocks. The list stays flat (header <li>, rows, footer <li>) so drag-reorder
   works across it; the block reads as one unit through a shared accent bar and tint. */
.block-header,
.exercise-row.in-block,
.block-footer {
  background: rgba(0, 136, 255, 0.04);
  border-left: 3px solid var(--color-accent);
  border-radius: 0;
}

.block-header {
  margin-top: 6px;
  border-bottom: 1px solid var(--color-border);
}

.block-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 8px 8px 10px;
  color: var(--color-accent);
  cursor: pointer;
  transition: background-color 0.1s;
}

.block-summary:hover {
  background: rgba(0, 136, 255, 0.06);
}

.block-chip {
  background: rgba(0, 136, 255, 0.12);
  border-radius: 999px;
  padding: 1px 9px;
  font-size: 13px;
  font-weight: 590;
}

.block-math {
  margin-left: auto;
  color: var(--color-label-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.block-edit {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 0 8px 10px 10px;
}

.block-edit .field-subtitle {
  margin: 0;
}

.block-edit-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.block-edit-controls .row-delete {
  margin-left: auto;
}

.block-stepper .stepper input {
  width: 52px;
}

.block-footer {
  min-height: 12px;
  margin-bottom: 6px;
}

.block-add-row {
  width: 100%;
  padding: 8px 10px;
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 14px;
  text-align: left;
  color: var(--color-accent);
  cursor: pointer;
  transition: background-color 0.15s;
}

.block-add-row:hover {
  background: rgba(0, 136, 255, 0.08);
}

/* Shown inside a block that has no exercises yet. Part of the block (same bar and tint)
   so a row dragged onto it lands inside. */
.block-placeholder {
  padding: 16px 10px;
  border-left: 3px solid var(--color-accent);
  border-bottom: 1px solid var(--color-border);
  background: rgba(0, 136, 255, 0.04);
  color: var(--color-label-secondary);
  font-size: 13px;
  text-align: center;
}

/* "Keep the exercises or delete them too?" — replaces the block's controls in place. */
.block-confirm-text {
  margin: 0;
  color: var(--color-label-primary);
  font-size: 14px;
}

.block-confirm-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.block-confirm-btn {
  padding: 7px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: white;
  font-family: inherit;
  font-size: 14px;
  color: var(--color-label-primary);
  cursor: pointer;
  transition:
    background-color 0.15s,
    border-color 0.15s,
    transform 0.1s;
}

.block-confirm-btn:hover {
  background: rgba(0, 0, 0, 0.04);
}

.block-confirm-btn:active {
  transform: scale(0.97);
}

.block-confirm-btn.danger {
  color: var(--color-warning);
  border-color: rgba(244, 51, 67, 0.35);
}

.block-confirm-btn.danger:hover {
  background: rgba(244, 51, 67, 0.08);
}

.block-confirm-btn.subtle {
  border-color: transparent;
  background: transparent;
  color: var(--color-label-secondary);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.field-label {
  font-size: 11px;
  font-weight: 510;
  color: var(--color-label-secondary);
}

.field-subtitle {
  font-size: 12px;
  color: var(--color-label-secondary);
  line-height: 1.4;
}

.field input[type='text'],
.field input[type='number'],
.field input[type='file'] {
  font-family: inherit;
  font-size: 15px;
  color: var(--color-label-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 8px;
  background: white;
}

.field input[type='text']:focus,
.field input[type='number']:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(0, 136, 255, 0.15);
}

.stepper {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  width: fit-content;
  /* No overflow:hidden here (used to clip the end buttons' corners) — it was also
     clipping their hover tooltips, since those escape upward past this box. The
     rounding is done per-button below instead. */
}

.stepper button:first-child {
  border-top-left-radius: var(--radius);
  border-bottom-left-radius: var(--radius);
}

.stepper button:last-child {
  border-top-right-radius: var(--radius);
  border-bottom-right-radius: var(--radius);
}

.stepper button {
  border: none;
  background: rgba(0, 0, 0, 0.04);
  width: 36px;
  font-size: 16px;
  cursor: pointer;
  transition: background-color 0.15s;
}

.stepper button:hover {
  background: rgba(0, 0, 0, 0.08);
}

.stepper button:active {
  background: rgba(0, 0, 0, 0.14);
}

.stepper input {
  width: 76px;
  border: none;
  text-align: center;
  font-family: inherit;
  font-size: 15px;
  -moz-appearance: textfield;
}

.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.media-thumb-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.media-thumb-card {
  position: relative;
  width: 84px;
}

/* A plain image or YouTube thumbnail is clickable (lightbox / reopen loop editor);
   an uploaded video isn't — it has its own native controls instead. */
.media-thumb-card:not(.is-video) img,
.media-thumb-card:not(.is-video) video {
  cursor: pointer;
  transition:
    filter 0.15s,
    transform 0.1s;
}

.media-thumb-card:not(.is-video):hover img,
.media-thumb-card:not(.is-video):hover video {
  filter: brightness(0.9);
}

.media-thumb-card:not(.is-video):active img,
.media-thumb-card:not(.is-video):active video {
  transform: scale(0.96);
}

.media-thumb-card img,
.media-thumb-card video {
  display: block;
  width: 84px;
  height: 84px;
  object-fit: cover;
  border-radius: var(--radius);
}

/* A video (never combined with other media) gets to be its own natural size with
   native controls, rather than squeezed into the small square image tiles. */
.media-thumb-card.is-video {
  width: fit-content;
}

.media-thumb-card.is-video video {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 160px;
  object-fit: contain;
}

.media-thumb-card.dragging {
  opacity: 0.5;
}

.media-thumb-order {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.media-thumb-remove {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.media-thumb-remove:hover {
  background: var(--color-warning);
}

.media-thumb-remove:active {
  transform: scale(0.9);
}

/* Account (top-right of My Workouts) and the sign-in screen */
.account {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.account-email {
  min-width: 0;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-label-secondary);
  font-size: 13px;
}

.account-btn {
  flex-shrink: 0;
  padding: 6px 10px;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  font-family: inherit;
  font-size: 14px;
  color: var(--color-accent);
  cursor: pointer;
  transition: background-color 0.15s;
}

.account-btn:hover {
  background: rgba(0, 136, 255, 0.08);
}

.sync-status {
  margin: 2px 0 12px;
  color: var(--color-label-secondary);
  font-size: 12px;
}

.sync-status[data-state='attention'],
.sync-status[data-state='retrying'] {
  color: var(--color-warning);
}

.sync-conflict {
  margin: 0 0 12px;
  padding: 12px;
  border-radius: var(--radius);
  background: rgba(244, 51, 67, 0.06);
  border: 1px solid rgba(244, 51, 67, 0.2);
}

.sync-conflict-text {
  margin: 0 0 10px;
  font-size: 14px;
  line-height: 1.4;
}

.sync-conflict-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.row-alert-flag {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  color: var(--color-warning);
}

.limit-notice {
  margin: 10px 0 0;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: rgba(0, 136, 255, 0.06);
  color: var(--color-label-primary);
  font-size: 14px;
  line-height: 1.4;
}

.auth-title {
  margin: 8px 0 8px;
  font-size: 22px;
  font-weight: 700;
}

.auth-lead {
  margin: 0 0 20px;
  color: var(--color-label-secondary);
  font-size: 14px;
  line-height: 1.5;
}

.auth-lead strong {
  color: var(--color-label-primary);
  font-weight: 500;
  overflow-wrap: anywhere;
}

.auth-hint {
  margin: 0 0 20px;
  color: var(--color-label-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.auth-notice {
  margin: 0 0 16px;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: rgba(244, 51, 67, 0.08);
  color: var(--color-warning);
  font-size: 14px;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.auth-input {
  width: 100%;
  padding: 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: white;
  font-family: inherit;
  font-size: 16px; /* 16px stops iOS from zooming the page when the field is focused */
  color: var(--color-label-primary);
}

.auth-input:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(0, 136, 255, 0.15);
}

.auth-code {
  font-size: 20px;
  letter-spacing: 6px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.auth-code-form {
  margin-bottom: 16px;
}

.auth-error {
  margin: 0;
  color: var(--color-warning);
  font-size: 14px;
}

.auth-primary,
.auth-secondary {
  padding: 12px;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 15px;
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.auth-primary {
  border: none;
  background: var(--color-accent);
  color: white;
  font-weight: 500;
}

.auth-primary:hover:not(:disabled) {
  background: #0077e6;
}

.auth-secondary {
  border: 1px solid var(--color-border);
  background: white;
  color: var(--color-label-primary);
}

.auth-secondary:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.04);
}

.auth-primary:active:not(:disabled),
.auth-secondary:active:not(:disabled) {
  transform: scale(0.98);
}

.auth-primary:disabled,
.auth-secondary:disabled {
  opacity: 0.6;
  cursor: default;
}

.auth-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.auth-link {
  padding: 8px;
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 14px;
  color: var(--color-accent);
  cursor: pointer;
}

.add-row-group {
  display: flex;
  gap: 8px;
  margin-top: 16px;
}

.add-row-group .add-row {
  flex: 1;
  width: auto;
  margin-top: 0;
}

.add-row {
  width: 100%;
  margin-top: 16px;
  padding: 12px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius);
  background: transparent;
  font-family: inherit;
  font-size: 15px;
  color: var(--color-accent);
  cursor: pointer;
  transition:
    background-color 0.15s,
    border-color 0.15s;
}

.add-row:hover {
  background: rgba(0, 136, 255, 0.05);
  border-color: rgba(0, 136, 255, 0.35);
}

.add-row:active {
  background: rgba(0, 136, 255, 0.1);
}

/* Playback screen */
.play-screen {
  /* --u is one "design pixel" of the Figma playback frame (571x397): the top-left HUD
     is specified in those pixels and scales with the screen's short side. The ring
     keeps its own sizing (--ring-size), unchanged from before the redesign. */
  --u: clamp(0.85px, calc(100vmin / 397), 3px);
  --ring-size: min(55vmin, 320px);
  /* The title's corner radius (4 design px) — shared by the badges and the pause buttons. */
  --play-radius: calc(4 * var(--u));
  position: fixed;
  inset: 0;
  background: #000;
  overflow: hidden;
  color: #f1eddc;
  user-select: none;
}

.play-media {
  position: absolute;
  inset: 0;
}

.play-media img,
.play-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* When multiple still images cycle, all are stacked and crossfaded via opacity
   rather than swapped outright, so the transition has no hard cut. */
.media-layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 60ms linear;
}

.media-layer.visible {
  opacity: 1;
}

/* Stands in for a YouTube video that can't be reached (see showVideoFallback). Sits in the
   lower part of the screen so it doesn't collide with the timer ring in the middle. */
.media-offline {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: calc(6 * var(--u));
  padding-bottom: max(16px, 7vmin);
  background: #14131c;
  color: rgba(255, 255, 255, 0.7);
}

.media-offline svg {
  width: calc(28 * var(--u));
  height: calc(28 * var(--u));
}

.media-offline p {
  margin: 0;
  font-size: calc(14 * var(--u));
  font-weight: 500;
}

/* A YouTube embed can't use object-fit, so oversize the iframe to a fixed 16:9 and
   center-crop it — the standard "responsive background video" trick. */
.yt-embed-host {
  overflow: hidden;
}

.yt-embed-host iframe {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100vw;
  height: 56.25vw;
  min-height: 100vh;
  min-width: 177.78vh;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* Top-left HUD. The exercise title always stays put; for the last few seconds "Next:"
   slides out to the right from *behind* it (the title's shadow falls on its edge).
   The row is flex so the Next badge starts 7 design px inside the title's right edge
   however wide the current title is. --hud-max leaves room for .exit-btn in the top-right
   corner: 36px button + 16px offset = 52px, plus a 22px gap. Anything in the HUD (the title, or
   the Next badge while it wobbles) stays inside it, and the gap is wide enough for the arrival
   wobble's overshoot (7% of the badge) even when the badge fills the whole width.
   The title may use the whole width; playView.js narrows it to 55% only while Next is out and
   the two don't fit together (see fitTitleForNext). */
.play-hud {
  position: absolute;
  top: calc(16 * var(--u));
  left: calc(16 * var(--u));
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(8 * var(--u));
  --hud-max: calc(100vw - 74px - 16 * var(--u));
  max-width: var(--hud-max);
  pointer-events: none;
}

.hud-row {
  display: flex;
  align-items: stretch;
  max-width: 100%;
}

.activity-banner {
  position: relative;
  z-index: 2;
  /* Never squeezed by the (hidden) Next badge next to it: the title takes what its name needs, up
     to the whole HUD, and a name that is longer than that ellipsizes. */
  flex: 0 0 auto;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: calc(10 * var(--u)) calc(16 * var(--u));
  border-radius: var(--play-radius);
  background: var(--play-label-bg);
  /* The shadow exists only to fall on the Next badge, so it's only there while Next is out. */
  box-shadow: 0 0 0 rgba(0, 0, 0, 0);
  /* max-width is what narrows the title when Next arrives (a px value set by playView.js). */
  transition:
    box-shadow 0.2s ease,
    max-width 0.25s ease-out;
  color: #fff;
  font-size: calc(20 * var(--u));
  font-weight: 800;
  line-height: normal;
}

.hud-row.next-out .activity-banner {
  box-shadow: calc(5 * var(--u)) 0 calc(2 * var(--u)) rgba(0, 0, 0, 0.25);
}

/* Clips the badge on the left/top/bottom so it's invisible while tucked behind the
   title, but leaves room on the right so the arrival wobble can overshoot visibly. */
.next-clip {
  position: relative;
  z-index: 1;
  display: flex;
  flex: 0 1 auto; /* takes what the title leaves, and shortens its text with an ellipsis if that is less than it needs */
  min-width: 0;
  margin-left: calc(-7 * var(--u));
  clip-path: inset(0 calc(-40 * var(--u)) 0 0);
}

.next-badge {
  display: flex;
  flex: 1;
  align-items: center;
  min-width: 0;
  padding: 0 calc(16 * var(--u));
  border-radius: var(--play-radius);
  background: var(--color-warning);
  color: var(--play-label-bg);
  font-size: calc(16 * var(--u));
  line-height: normal;
  transform: translateX(-100%); /* resting state: hidden behind the title (see showNextPreview) */
}

/* While Next hands over to the title the badge travels left past this clip. */
.next-clip.handoff {
  clip-path: none;
}

/* ...and, while it turns into the title, grows or shrinks (a width animation set by playView.js)
   to the width the real title will have, instead of following the clip's width. */
.next-badge.growing {
  flex: 0 0 auto;
}

@media (prefers-reduced-motion: reduce) {
  .activity-banner {
    transition: box-shadow 0.2s ease;
  }
}

.next-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.next-label {
  /* inline-block so the label can collapse to nothing when Next turns into the title */
  display: inline-block;
  vertical-align: top;
  overflow: hidden;
  white-space: pre;
  font-weight: 500;
}

.next-name {
  font-weight: 700;
}

.round-badge {
  padding: calc(6 * var(--u)) calc(12 * var(--u));
  border-radius: var(--play-radius);
  background: var(--play-round-bg);
  color: rgba(255, 255, 255, 0.7);
  font-size: calc(14 * var(--u));
  font-weight: 600;
  line-height: normal;
  white-space: nowrap;
}

.timer-wrap {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--ring-size);
  aspect-ratio: 1;
  transition: opacity 0.2s ease;
}

/* Only one thing owns the screen's center at a time — when paused, the ring fades
   out to make room for the pause state instead of the two fighting for the same spot. */
.timer-wrap.timer-wrap-hidden {
  opacity: 0;
  pointer-events: none;
}

.timer-ring {
  /* block, not inline: an inline SVG sits on the text baseline and leaves a few px of
     descender gap below it, which pushed the ring off the center of its plate. */
  display: block;
  width: 100%;
  height: 100%;
}

.timer-ring-bg {
  fill: none;
  stroke: rgba(255, 255, 255, 0.25);
}

.timer-ring-fg {
  fill: none;
  stroke: var(--color-warning);
  stroke-linecap: butt;
}

.timer-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 45%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--play-label-bg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.timer-badge.warning {
  background: var(--color-warning);
}

/* 42px in the 180px Figma ring, so the number keeps that proportion to the ring. */
.timer-number {
  font-weight: 900;
  font-size: calc(var(--ring-size) * 0.233);
  line-height: 1;
  color: #fff;
}

.timer-badge.warning .timer-number {
  color: #1a1a1a;
}

.exit-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.4);
  color: #fff;
  font-size: 16px;
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.exit-btn:hover {
  background: rgba(0, 0, 0, 0.6);
}

.exit-btn:active {
  transform: scale(0.9);
}

.pause-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 24px;
  transition: background-color 0.2s ease;
}

.pause-overlay[hidden] {
  display: none;
}

/* width:100% here gives .pause-actions' own width:100% a definite containing block
   to resolve against — without it, .pause-content (a shrink-to-fit flex item with no
   width of its own) leaves that percentage with nothing real to resolve against, so
   it falls back to shrink-wrapping instead of actually filling the available width. */
.pause-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
}

/* Every piece of the pause state cascades in with a small delay after the last —
   a bit of life instead of the whole group just appearing at once. */
.pause-content > * {
  animation: pauseFadeUp 0.28s cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

.pause-content > *:nth-child(1) {
  animation-delay: 0s;
}
.pause-content > *:nth-child(2) {
  animation-delay: 0.04s;
}
.pause-content > *:nth-child(3) {
  animation-delay: 0.08s;
  margin-top: 14px;
}

@keyframes pauseFadeUp {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.pause-icon-circle {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Longhand overrides win over the shorthand on .pause-content > * (equal
     specificity, later in source) — adds the pop without losing the fade/rise. */
  animation-name: pauseIconPop, pauseFadeUp;
  animation-duration: 0.35s, 0.28s;
  animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1), cubic-bezier(0.2, 0.8, 0.2, 1);
}

@keyframes pauseIconPop {
  from {
    transform: scale(0.6);
  }
  to {
    transform: scale(1);
  }
}

/* Big and bold — pausing is at least as important a moment as the exercise name itself. */
.pause-title {
  margin: 0;
  font-size: clamp(24px, 6vw, 48px);
  font-weight: 700;
}

/* max-width matches #app's own content width (480px) — the usual cap this codebase
   uses for "how wide should content get on a large screen." On a phone, width:100%
   is already bounded by the overlay's own side padding, so this only changes
   anything once there's real room to give the buttons — never squeezes mobile. */
.pause-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  width: 100%;
  max-width: 480px;
}

/* The primary action — filled light, dark text, a moderate rounded-rect radius
   (not the old full pill) so it reads as a solid, tappable card rather than a
   floating capsule. An explicit button now, so the old "tap anywhere" hint text
   would just be redundant — removed. */
.pause-resume-btn {
  border: none;
  border-radius: var(--play-radius);
  background: #f1eddc;
  color: var(--play-label-bg);
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
  padding: 14px 20px;
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.pause-resume-btn:hover {
  background: #fff;
}

.pause-resume-btn:active {
  transform: scale(0.96);
}

/* Restart/Previous/Next share one dark "platta" (plate) as a segmented control —
   a divider between segments rather than gaps between separate pills. Rounding is
   applied per-edge-segment (not overflow:hidden on the wrapper) so a segment's
   hover tooltip isn't clipped by the plate's own bounds. */
.pause-actions-secondary {
  display: flex;
  background: rgba(255, 255, 255, 0.1);
  border-radius: var(--play-radius);
}

/* Icon stacked above label — consistent for all three segments regardless of label
   length, instead of an inline icon+text pair that only wrapped for the longer
   ones ("Previous"/"Next" but not "Restart"). */
.pause-action-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  border: none;
  border-right: 1px solid rgba(255, 255, 255, 0.12);
  background: transparent;
  color: #fff;
  font-family: inherit;
  font-size: 13px;
  font-weight: 510;
  padding: 12px 16px;
  cursor: pointer;
  transition: background-color 0.15s;
}

.pause-action-btn:last-child {
  border-right: none;
}

.pause-action-btn:first-child {
  border-top-left-radius: var(--play-radius);
  border-bottom-left-radius: var(--play-radius);
}

.pause-action-btn:last-child {
  border-top-right-radius: var(--play-radius);
  border-bottom-right-radius: var(--play-radius);
}

.pause-action-btn:hover {
  background: rgba(255, 255, 255, 0.08);
}

.pause-action-btn:active {
  background: rgba(255, 255, 255, 0.16);
}

.pause-action-icon {
  flex-shrink: 0;
}

.pause-action-icon-mirror {
  transform: scaleX(-1);
}

/* Done screen */
.done-screen {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  text-align: center;
}

.done-screen h1 {
  font-size: 32px;
  margin: 0;
}

.done-summary {
  color: var(--color-label-secondary);
  font-size: 15px;
  margin: 0 0 12px;
}

.done-back-btn {
  border: none;
  border-radius: var(--radius);
  background: var(--color-accent);
  color: white;
  font-family: inherit;
  font-size: 15px;
  padding: 10px 20px;
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.done-back-btn:hover {
  background: #0077e0;
}

.done-back-btn:active {
  transform: scale(0.96);
}

/* YouTube media thumbnail (setup list): just a static image, so mark it as playable
   and show the chosen loop range, and make the whole thing tap to re-edit. */
.media-thumb-card.youtube {
  cursor: pointer;
}

.media-thumb-play-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  pointer-events: none;
}

.media-thumb-range-label {
  position: absolute;
  bottom: 6px;
  left: 6px;
  background: rgba(0, 0, 0, 0.6);
  color: white;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 4px;
  pointer-events: none;
}

/* YouTube loop-range editor screen */
.yt-range-screen {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.yt-range-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.yt-range-back {
  border: none;
  background: transparent;
  color: var(--color-accent);
  font-family: inherit;
  font-size: 15px;
  padding: 4px 0;
  cursor: pointer;
  transition: opacity 0.15s;
}

.yt-range-back:hover {
  opacity: 0.7;
}

.yt-range-back:active {
  opacity: 0.5;
}

.yt-range-title {
  font-weight: 700;
  font-size: 16px;
}

.yt-range-player {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: var(--radius);
  overflow: hidden;
}

.yt-range-player iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.yt-range-hint {
  font-size: 13px;
  color: var(--color-label-secondary);
  margin: 0;
}

.yt-range-track {
  position: relative;
  height: 36px;
  background: rgba(0, 0, 0, 0.06);
  border-radius: var(--radius);
}

.yt-range-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  background: rgba(0, 136, 255, 0.25);
}

.yt-range-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 14px;
  margin-left: -7px;
  background: var(--color-accent);
  border-radius: 4px;
  cursor: grab;
  touch-action: none;
  transition: background-color 0.15s;
}

.yt-range-handle:hover {
  background: #0077e0;
}

.yt-range-handle:active {
  cursor: grabbing;
  background: #0066c4;
}

.yt-range-times {
  text-align: center;
  font-size: 15px;
  font-weight: 510;
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.yt-range-actions {
  display: flex;
  gap: 10px;
}

.yt-range-preview-btn,
.yt-range-save-btn {
  flex: 1;
  border: none;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 15px;
  padding: 12px;
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.yt-range-preview-btn:active,
.yt-range-save-btn:not(:disabled):active {
  transform: scale(0.97);
}

.yt-range-preview-btn {
  background: rgba(0, 0, 0, 0.06);
  color: var(--color-label-primary);
}

.yt-range-preview-btn:hover {
  background: rgba(0, 0, 0, 0.1);
}

.yt-range-save-btn {
  background: var(--color-accent);
  color: white;
}

.yt-range-save-btn:hover:not(:disabled) {
  background: #0077e0;
}

.yt-range-save-btn:disabled {
  background: rgba(0, 0, 0, 0.15);
  cursor: not-allowed;
}

/* Full-size image viewer — click anywhere to close. */
.image-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
}

.image-lightbox[hidden] {
  display: none;
}

.image-lightbox img {
  max-width: 100vw;
  max-height: 100vh;
  object-fit: contain;
}

/* ---- Exercise editor (js/exerciseView.js) --------------------------------------------------
   Grouped white cards on a grey page, after the Figma sketch. The page is grey while the editor
   is open (body.ex-editing, set by the view); the screen slides up as it opens. */
body.ex-editing {
  background: var(--color-sheet-bg);
}

.ex-editor {
  display: flex;
  flex-direction: column;
  padding-bottom: 32px;
  border-radius: 12px;
  animation: ex-in 0.28s cubic-bezier(0.2, 0.9, 0.3, 1);
}

@keyframes ex-in {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ex-editor,
  .ex-status svg,
  .ex-seg-thumb {
    animation: none;
    transition: none;
  }
}

/* Dropping a file or link anywhere on the screen adds it. */
.ex-editor.drop-active {
  outline: 2px dashed rgba(0, 136, 255, 0.5);
  outline-offset: 6px;
}

.ex-head {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 2px 0 4px;
}

.ex-title-wrap {
  text-align: center;
}

.ex-title {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
}

/* "All changes saved" — Done only leaves, so this says nothing is waiting to be confirmed. */
.ex-status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 16px;
  font-size: 12px;
  color: var(--color-label-secondary);
}

.ex-status svg {
  color: #1f9d55;
  animation: ex-pop 0.25s cubic-bezier(0.3, 1.4, 0.5, 1);
}

@keyframes ex-pop {
  from {
    opacity: 0;
    transform: scale(0.4);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.ex-done {
  justify-self: end;
  padding: 8px 0 8px 12px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 17px;
  font-weight: 500;
  color: var(--color-accent);
  cursor: pointer;
  transition: opacity 0.15s;
}

.ex-done:hover {
  opacity: 0.7;
}

.ex-done:active {
  opacity: 0.5;
}

/* A hint that Escape closes the editor, only where there is a keyboard. */
.ex-esc {
  visibility: hidden; /* still takes its column, so the title stays centred */
  justify-self: start;
  padding: 1px 6px;
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 4px;
  font-size: 11px;
  color: var(--color-label-secondary);
}

@media (hover: hover) and (pointer: fine) {
  .ex-esc {
    visibility: visible;
  }
}

.ex-section {
  margin: 20px 4px 6px;
  font-size: 13px;
  font-weight: 400;
  color: var(--color-label-secondary);
}

.ex-card-first {
  margin-top: 8px;
}

.ex-card-last {
  margin-top: 22px;
}

.ex-card {
  background: white;
  border-radius: 12px;
  overflow: hidden;
}

.ex-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 0 12px 0 14px;
  transition: background-color 0.15s;
}

.ex-row ~ .ex-row {
  border-top: 0.5px solid rgba(0, 0, 0, 0.12);
}

.ex-row:focus-within {
  background: rgba(0, 0, 0, 0.025);
}

.ex-row-plain:focus-within {
  background: none;
}

.ex-label {
  flex: none;
  width: 72px;
  font-size: 16px;
}

.ex-label-grow {
  flex: 1;
  width: auto;
}

.ex-unit-note {
  font-size: 14px;
  color: var(--color-label-secondary);
}

.ex-input {
  flex: 1;
  min-width: 0;
  height: 46px;
  padding: 0;
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 16px;
  color: var(--color-label-primary);
  outline: none;
}

.ex-input::placeholder {
  color: rgba(0, 0, 0, 0.3);
}

.ex-pill {
  flex: none;
  height: 32px;
  padding: 0 14px;
  border: none;
  border-radius: 16px;
  background: var(--color-sheet-bg);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-accent);
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.ex-pill:hover {
  background: rgba(0, 136, 255, 0.12);
}

.ex-pill:active {
  transform: scale(0.95);
}

.ex-row-error {
  margin: 0;
  padding: 0 14px 8px;
  font-size: 12px;
  color: var(--color-warning);
}

/* The whole row is the button: choose a file. */
.ex-row-button {
  width: 100%;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 16px;
  text-align: left;
  color: var(--color-label-primary);
  cursor: pointer;
}

.ex-row-button:hover {
  background: rgba(0, 0, 0, 0.025);
}

.ex-row-button:active {
  background: rgba(0, 0, 0, 0.05);
}

.ex-row-button svg:first-child {
  color: var(--color-accent);
}

.ex-row-button svg:last-child {
  color: rgba(0, 0, 0, 0.3);
}

.ex-row-text {
  flex: 1;
}

.ex-hint {
  margin: 6px 4px 0;
  font-size: 12px;
  color: var(--color-label-secondary);
}

.ex-notice {
  margin: 8px 0 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: rgba(244, 51, 67, 0.08);
  font-size: 13px;
  color: var(--color-warning);
}

.ex-strip {
  margin-top: 12px;
  padding: 12px;
}

.ex-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 18px 0;
  font-size: 14px;
  color: var(--color-label-secondary);
}

.ex-strip-hint {
  margin: 10px 0 0;
  font-size: 12px;
  color: var(--color-label-secondary);
}

/* Segmented control, the iOS way: one grey pill, and a white thumb that slides to the chosen segment. */
.ex-seg-wrap {
  padding: 12px 12px 4px;
}

.ex-seg {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--seg-count, 2), 1fr);
  padding: 2px;
  border-radius: 9px;
  background: rgba(118, 118, 128, 0.12);
}

.ex-seg-thumb {
  position: absolute;
  top: 2px;
  bottom: 2px;
  left: 2px;
  width: calc((100% - 4px) / var(--seg-count, 2));
  border-radius: 7px;
  background: white;
  box-shadow:
    0 3px 8px rgba(0, 0, 0, 0.12),
    0 1px 1px rgba(0, 0, 0, 0.06),
    0 0 0 0.5px rgba(0, 0, 0, 0.04);
  transform: translateX(calc(var(--seg-index, 0) * 100%));
  transition: transform 0.3s cubic-bezier(0.3, 0.9, 0.3, 1.05);
}

.ex-seg-btn {
  position: relative;
  z-index: 1;
  height: 32px;
  border: none;
  border-radius: 7px;
  background: none;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-label-primary);
  cursor: pointer;
}

.ex-seg-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.ex-stepper {
  display: flex;
  align-items: center;
  padding: 2px;
  border-radius: 9px;
  background: var(--color-sheet-bg);
}

.ex-stepper button {
  width: 40px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 7px;
  background: none;
  font-family: inherit;
  font-size: 20px;
  color: var(--color-label-primary);
  cursor: pointer;
  transition:
    background-color 0.15s,
    transform 0.1s;
}

.ex-stepper button:hover {
  background: white;
}

.ex-stepper button:active {
  transform: scale(0.92);
}

.ex-stepper input {
  width: 56px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 7px;
  background: transparent;
  font-family: inherit;
  font-size: 16px;
  font-weight: 500;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--color-label-primary);
  outline: none;
  appearance: textfield;
  -moz-appearance: textfield;
}

.ex-stepper input:focus {
  background: white;
  box-shadow: 0 0 0 2px rgba(0, 136, 255, 0.35);
}

.ex-stepper input::-webkit-outer-spin-button,
.ex-stepper input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.ex-delete {
  width: 100%;
  height: 48px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 16px;
  color: var(--color-warning);
  cursor: pointer;
  transition: background-color 0.15s;
}

.ex-delete:hover {
  background: rgba(244, 51, 67, 0.06);
}

.ex-confirm {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px 8px 14px;
}

.ex-confirm-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
}

/* iOS Safari zooms the page in when a field whose text is smaller than 16px gets focus, and
   leaves it zoomed. Touch screens therefore get at least 16px in every field; desktops keep the
   tighter sizes above. Last in the file so it wins over the per-field sizes. The fields that are
   already larger than 16px (the workout title, the sign-in code) are left alone: this must
   only ever raise a size. */
@media (pointer: coarse) {
  input:not([type='file']):not([type='checkbox']):not([type='radio']):not([type='range']):not(.workout-title):not(.auth-code),
  select,
  textarea {
    font-size: 16px;
  }
}
