/* Roma components. Requires tokens/tokens.css.
   Classes use the tl- (Tomato Lab) prefix so they survive a rename of the system.
   The .is-hover / .is-pressed / .is-focus classes only exist to show states in the docs. */

/* ---------- Motion ----------
   One easing and two durations for every state change: quick for color and press, base for movement.
   Nothing bounces; things settle. Reduced motion turns it all off at the bottom of this file. */
:root {
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-quick: 160ms;
  --dur-base: 280ms;
}

/* ---------- Button ---------- */
.tl-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-8);
  height: var(--control-height-md);
  padding: 0 var(--space-24);
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--color-action-primary-bg);
  color: var(--color-action-primary-text);
  font: var(--text-action-md);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  -webkit-font-smoothing: antialiased;
  transition: background-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), transform var(--dur-quick) var(--ease-out);
}
.tl-button:active:not(:disabled) { transform: translateY(1px); }
.tl-button:hover, .tl-button.is-hover { background: var(--color-action-primary-bg-hover); }
.tl-button:active, .tl-button.is-pressed { background: var(--color-action-primary-bg-pressed); }

.tl-button--secondary { background: var(--color-action-secondary-bg); color: var(--color-action-secondary-text); }
.tl-button--secondary:hover, .tl-button--secondary.is-hover { background: var(--color-action-secondary-bg-hover); }
.tl-button--secondary:active, .tl-button--secondary.is-pressed { background: var(--color-action-secondary-bg-pressed); }

.tl-button--outline {
  background: transparent;
  color: var(--color-text-primary);
  box-shadow: inset 0 0 0 var(--border-width-2) var(--color-border-default);
}
.tl-button--outline:hover, .tl-button--outline.is-hover { background: var(--color-bg-muted); }
.tl-button--outline:active, .tl-button--outline.is-pressed { background: var(--color-bg-inverse); color: var(--color-text-inverse); }

.tl-button--lg { height: var(--control-height-lg); padding: 0 var(--space-32); font: var(--text-action-lg); }

.tl-button:disabled, .tl-button[aria-disabled="true"] {
  background: var(--color-action-disabled-bg);
  color: var(--color-action-disabled-text);
  box-shadow: none;
  cursor: not-allowed;
}
.tl-button--outline:disabled, .tl-button--outline[aria-disabled="true"] {
  background: transparent;
  box-shadow: inset 0 0 0 var(--border-width-2) var(--color-border-subtle);
}

/* ---------- Text input ---------- */
.tl-field { display: grid; gap: var(--space-8); max-width: 100%; }
.tl-field__label { font: var(--text-label-m); color: var(--color-text-primary); }
.tl-field__help { display: flex; align-items: center; gap: var(--space-4); font: var(--text-caption); color: var(--color-text-secondary); }

.tl-input {
  box-sizing: border-box;
  width: 100%;
  height: var(--control-height-md);
  padding: 0 var(--space-16);
  border: var(--border-width-1) solid var(--color-border-default);
  border-radius: var(--radius-none);
  background: var(--color-bg-surface);
  color: var(--color-text-primary);
  font: var(--text-body-m);
}
.tl-input::placeholder { color: var(--color-text-muted); opacity: 1; }
.tl-input:hover, .tl-input.is-hover { box-shadow: inset 0 0 0 var(--border-width-1) var(--color-border-default); }
.tl-input:focus-visible, .tl-input.is-focus {
  outline: none;
  border-color: var(--color-border-focus);
  box-shadow: inset 0 0 0 var(--border-width-1) var(--color-border-focus);
}
.tl-input[aria-invalid="true"] {
  border-color: var(--color-feedback-danger-fg);
  box-shadow: inset 0 0 0 var(--border-width-1) var(--color-feedback-danger-fg);
}
.tl-input:disabled {
  background: var(--color-action-disabled-bg);
  border-color: var(--color-border-subtle);
  color: var(--color-action-disabled-text);
  box-shadow: none;
  cursor: not-allowed;
}
.tl-field:has(.tl-input:disabled) .tl-field__label,
.tl-field:has(.tl-input:disabled) .tl-field__help { color: var(--color-text-muted); }
.tl-field:has(.tl-input[aria-invalid="true"]) .tl-field__help { color: var(--color-feedback-danger-fg); }
.tl-field:has(.tl-input[aria-invalid="true"]) .tl-field__help::before {
  content: "!";
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-full);
  background: var(--color-feedback-danger-fg);
  color: var(--color-bg-surface);
  font: 900 11px/1 var(--font-text);
}

/* ---------- Checkbox, radio, toggle ---------- */
.tl-choice {
  display: inline-flex;
  align-items: center;
  gap: var(--space-12);
  font: var(--text-body-m);
  color: var(--color-text-primary);
  cursor: pointer;
}
.tl-choice:has(input:disabled) { color: var(--color-text-muted); cursor: not-allowed; }

.tl-checkbox, .tl-radio, .tl-toggle {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  margin: 0;
  box-sizing: border-box;
  border: var(--border-width-2) solid var(--color-border-default);
  background: var(--color-bg-surface);
  cursor: inherit;
}
.tl-checkbox:hover, .tl-checkbox.is-hover,
.tl-radio:hover, .tl-radio.is-hover,
.tl-toggle:hover, .tl-toggle.is-hover { background-color: var(--color-bg-muted); }
.tl-checkbox.is-focus, .tl-radio.is-focus, .tl-toggle.is-focus {
  outline: var(--border-width-2) solid var(--color-border-focus);
  outline-offset: 2px;
}

.tl-checkbox { width: 24px; height: 24px; border-radius: var(--radius-none); display: inline-grid; place-items: center; }
.tl-checkbox::after { content: ""; width: 14px; height: 14px; }
.tl-checkbox:checked, .tl-checkbox:indeterminate {
  background-color: var(--color-action-primary-bg);
  border-color: var(--color-action-primary-bg);
}
.tl-checkbox:checked:hover, .tl-checkbox:checked.is-hover { background-color: var(--color-action-primary-bg-hover); }
.tl-checkbox:checked::after {
  background: var(--color-action-primary-text);
  clip-path: polygon(10% 52%, 24% 38%, 40% 55%, 78% 14%, 92% 28%, 40% 82%);
}
.tl-checkbox:indeterminate::after { height: 3px; width: 12px; background: var(--color-action-primary-text); }

.tl-radio { width: 24px; height: 24px; border-radius: var(--radius-full); }
.tl-radio:checked {
  border-color: var(--color-action-primary-bg);
  background-image: radial-gradient(circle, var(--color-action-primary-bg) 5.5px, transparent 6px);
}

.tl-toggle { position: relative; width: 48px; height: 28px; border-radius: var(--radius-full); }
.tl-toggle::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: var(--radius-full);
  background: var(--color-border-default);
  transition: transform var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}
.tl-toggle:checked { background-color: var(--color-action-primary-bg); border-color: var(--color-action-primary-bg); }
.tl-toggle:checked:hover, .tl-toggle:checked.is-hover { background-color: var(--color-action-primary-bg-hover); }
.tl-toggle:checked::before { transform: translateX(20px); background: var(--color-action-primary-text); }
@media (prefers-reduced-motion: reduce) { .tl-toggle::before { transition: none; } }

.tl-checkbox:disabled, .tl-radio:disabled, .tl-toggle:disabled {
  background-color: var(--color-action-disabled-bg);
  border-color: var(--color-border-subtle);
}
.tl-checkbox:disabled::after, .tl-toggle:disabled::before { background: var(--color-action-disabled-text); }
.tl-radio:checked:disabled { background-image: radial-gradient(circle, var(--color-action-disabled-text) 5.5px, transparent 6px); }

/* ---------- Tag and badge ---------- */
.tl-tag {
  display: inline-flex;
  align-items: center;
  padding: var(--space-4) var(--space-8);
  border-radius: var(--radius-none);
  background: var(--color-bg-muted);
  color: var(--color-text-primary);
  box-shadow: inset 0 0 0 var(--border-width-1) var(--color-border-subtle);
  font: var(--text-label-s);
  white-space: nowrap;
}
.tl-tag--inverse { background: var(--color-bg-inverse); color: var(--color-text-inverse); box-shadow: none; }
.tl-tag--danger { background: var(--color-feedback-danger-bg); color: var(--color-feedback-danger-fg); box-shadow: none; }
.tl-tag--success { background: var(--color-feedback-success-bg); color: var(--color-feedback-success-fg); box-shadow: none; }
.tl-tag--info { background: var(--color-feedback-info-bg); color: var(--color-feedback-info-fg); box-shadow: none; }
.tl-tag--warning { background: var(--color-feedback-warning-bg); color: var(--color-feedback-warning-fg); box-shadow: none; }

.tl-badge {
  display: inline-grid;
  place-items: center;
  box-sizing: border-box;
  min-width: 24px;
  height: 24px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-full);
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
  font: var(--text-label-s);
}
.tl-badge--dot { min-width: 0; width: 12px; height: 12px; padding: 0; background: var(--color-bg-accent); }

/* ---------- Provenance label ----------
   Says a photo, video or recording was made by people and not generated by AI.
   Sits beside a caption or source line, or over the media itself (--media).
   --mark is the mark alone, for tight spaces: give it role="img" and an aria-label. */
.tl-provenance {
  --tl-provenance-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='6.75' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M5 8.3l2.2 2.2L11 5.8' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='square'/%3E%3C/svg%3E");
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-4) var(--space-8);
  border-radius: var(--radius-none);
  background: transparent;
  color: var(--color-text-primary);
  box-shadow: inset 0 0 0 var(--border-width-1) var(--color-border-default);
  font: var(--text-label-s);
  white-space: nowrap;
}
.tl-provenance::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: var(--tl-provenance-mark) center / contain no-repeat;
  mask: var(--tl-provenance-mark) center / contain no-repeat;
}
.tl-provenance--media { background: var(--color-bg-inverse); color: var(--color-text-inverse); box-shadow: none; }
.tl-provenance--mark { gap: 0; padding: var(--space-4); }

/* Visually hidden text for screen readers */
.tl-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Provenance label, animated in (for video and for the first time it appears).
   The mark scales up from nothing with an elastic overshoot; then the rest of the
   chip and its text open out from behind it, a mask wiping left to right.
   Add --animate; remove and add it again to replay. Off under prefers-reduced-motion.
   For footage, the same animation is rendered with a transparent background in assets/provenance/. */
@keyframes tl-provenance-in { from { opacity: 0; } to { opacity: var(--tl-provenance-opacity, 1); } }
@keyframes tl-provenance-mark {
  0%   { transform: scale(0); }
  34%  { transform: scale(1.28); }
  54%  { transform: scale(0.88); }
  72%  { transform: scale(1.07); }
  88%  { transform: scale(0.98); }
  100% { transform: scale(1); }
}
@keyframes tl-provenance-open {
  from { clip-path: inset(0 calc(100% - 30px) 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}
.tl-provenance--animate {
  animation: tl-provenance-in 120ms linear both, tl-provenance-open 560ms var(--ease-out) 640ms both;
}
.tl-provenance--animate::before {
  transform-origin: center;
  animation: tl-provenance-mark 720ms cubic-bezier(0.25, 0.6, 0.35, 1) both;
}
.tl-provenance--mark.tl-provenance--animate { animation: tl-provenance-in 120ms linear both; }
@media (prefers-reduced-motion: reduce) {
  .tl-provenance--animate, .tl-provenance--animate::before { animation: none; }
}

/* ---------- Media players ----------
   Audio and video, wired up by assets/roma.js. A panel with a solid Tomato play button (the primary action
   role, so it is white on the Tomato theme), light type and tabular times. The waveform shows the whole track
   dim; what has played turns the action color, led by a vertical line with a soft glow. Video uses the same
   panel, the picture at the top and the controls on their own rows below it. Add data-provenance to a video
   to lay the Human made label over the picture (data-provenance="animate" plays it in on first play). */
.tl-audio, .tl-video {
  --tl-media-played: var(--color-action-primary-bg);
  --tl-media-rest: var(--color-text-primary);
  --tl-media-soft: color-mix(in srgb, var(--color-text-primary) 7%, transparent);
  --tl-media-softer: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
  display: grid;
  gap: var(--space-16);
  box-sizing: border-box;
  width: 100%;
  max-width: 720px;
  padding: var(--space-24) 28px;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-text-primary) 4%, var(--color-bg-page));
  box-shadow: inset 0 0 0 var(--border-width-1) color-mix(in srgb, var(--color-text-primary) 10%, transparent);
  color: var(--color-text-primary);
  container-type: inline-size;
}
.tl-audio audio { display: none; }
/* the video's panel is the audio player's; only the picture and the scrubber differ (below) */
.tl-audio-row { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
/* In a narrow player the title takes its own line above the buttons */
@container (max-width: 400px) {
  .tl-audio-row { flex-wrap: wrap; }
  .tl-audio .tl-audio-meta { order: -2; flex: 1 0 calc(100% - 56px); margin: 0 0 var(--space-12); }
  .tl-audio-row .tl-media-cc { order: -1; align-self: flex-start; }
}
.tl-media-btn, .tl-media-play {
  display: inline-grid; place-items: center; flex: none;
  width: 40px; height: 40px; padding: 0; margin: 0;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--color-text-secondary);
  font-family: var(--font-text); font-size: 12px; font-weight: 400; font-variant-numeric: tabular-nums; letter-spacing: 0.04em;
  cursor: pointer;
  transition: background-color var(--dur-quick) var(--ease-out), color var(--dur-quick) var(--ease-out), box-shadow var(--dur-quick) var(--ease-out);
}
.tl-media-btn:hover { background: var(--tl-media-soft); color: var(--color-text-primary); }
.tl-media-play { width: 52px; height: 52px; border-radius: var(--radius-sm); background: var(--color-action-primary-bg); color: var(--color-action-primary-text); }
.tl-media-play:hover { background: var(--color-action-primary-bg-hover); color: var(--color-action-primary-text); }
.tl-media-play:active { background: var(--color-action-primary-bg-pressed); transform: translateY(1px); }
.tl-media-btn svg { width: 22px; height: 22px; fill: currentColor; }
.tl-media-play svg { width: 20px; height: 20px; fill: currentColor; }
.tl-media-btn:focus-visible, .tl-media-play:focus-visible, .tl-audio-wave:focus-visible, .tl-video-track:focus-visible {
  outline: var(--border-width-2) solid var(--color-border-focus); outline-offset: 2px;
}
.tl-audio-meta { display: grid; gap: 2px; min-width: 0; margin-left: var(--space-16); }
.tl-audio-kicker { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-text); font-size: 13px; letter-spacing: 0.01em; color: var(--color-text-muted); }
.tl-audio-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--text-heading-s); }

/* The waveform is the scrubber: the whole track dim, the part heard in the action color, a slider for the keyboard */
.tl-audio-wave {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  height: 56px;
  cursor: pointer; touch-action: none;
}
.tl-audio-wave i {
  flex: none; width: 2px; height: max(3px, var(--h, 50%)); border-radius: 2px;
  background: var(--tl-media-rest);
  opacity: 0.22;
  transition: opacity var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}
.tl-audio-wave:hover i:not(.is-played) { opacity: 0.32; }
.tl-audio-wave i.is-played { background: var(--tl-media-played); opacity: 1; }
/* now: a vertical line in the action color with a soft glow */
.tl-audio-head {
  position: absolute; top: -6px; bottom: -6px; left: var(--at, 0%);
  width: 2px; margin-left: -1px; border-radius: 2px;
  background: var(--tl-media-played);
  box-shadow: 0 0 10px 1px color-mix(in srgb, var(--tl-media-played) 70%, transparent), 0 0 26px 6px color-mix(in srgb, var(--tl-media-played) 35%, transparent);
  pointer-events: none;
}
.tl-media-time { display: flex; justify-content: space-between; font-family: var(--font-text); font-size: 13px; font-variant-numeric: tabular-nums; color: var(--color-text-muted); }
/* Captions: a CC toggle at the end of the row, and the current line under the times */
.tl-media-cc { width: auto; height: 28px; padding: 0 var(--space-8); border-radius: var(--radius-sm); box-shadow: inset 0 0 0 var(--border-width-1) var(--tl-media-softer); }
.tl-audio-row .tl-media-cc { margin-left: auto; }
.tl-media-cc[aria-pressed="true"] { background: var(--tl-media-softer); color: var(--color-text-primary); box-shadow: none; }
.tl-audio-caption {
  --cap-h: 4.2em;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  margin: calc(-1 * var(--space-16)) 0 0; max-width: none;
  /* closed until the first line arrives, then it slides open to a fixed height and stays there,
     so a wrapping cue never changes the player's size or moves anything around it */
  height: 0; overflow: hidden; opacity: 0;
  font-family: var(--font-text); font-size: 17px; line-height: 1.4; color: var(--color-text-secondary);
  transition: height var(--dur-base) var(--ease-out), margin-top var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
@container (min-width: 400px) { .tl-audio-caption { --cap-h: 2.8em; -webkit-line-clamp: 2; } }
.tl-audio.has-captions.is-captioning .tl-audio-caption { height: var(--cap-h); margin-top: 0; opacity: 1; }

/* Video: the same panel as the audio player, the picture at the top and the controls on their own rows below */
.tl-video { max-width: 960px; }
.tl-video-frame { position: relative; display: block; overflow: hidden; border-radius: var(--radius-sm); background: var(--color-neutral-900); }
.tl-video video { display: block; width: 100%; height: auto; background: var(--color-neutral-900); cursor: pointer; }
/* Human made label, over the picture. Hidden until the first play when it animates in. */
.tl-video-frame > .tl-provenance { position: absolute; right: var(--space-12); bottom: var(--space-12); z-index: 1; pointer-events: none;
  transform: scale(0.75); transform-origin: right bottom; --tl-provenance-opacity: 0.55; opacity: var(--tl-provenance-opacity); }
.tl-video-frame > .tl-provenance[hidden] { display: none; }
.tl-video-frame:fullscreen { display: grid; place-items: center; border-radius: 0; background: #000; }
.tl-video-frame:fullscreen video { max-height: 100vh; }
.tl-video video::cue { font-family: var(--font-text); background: rgb(0 0 0 / 0.6); color: var(--color-neutral-50); }
.tl-video .tl-audio-row { margin-top: var(--space-4); }
.tl-media-tools { display: flex; align-items: center; gap: var(--space-4); margin-left: auto; padding-left: var(--space-8); }
.tl-video .tl-media-cc { margin-left: 0; }
/* the scrubber: a slim rounded line, the played part in the action color, now a glowing line */
.tl-video-track { position: relative; height: 24px; cursor: pointer; touch-action: none; }
.tl-video-track::before, .tl-video-fill { content: ""; position: absolute; left: 0; top: 10px; height: 4px; border-radius: 4px; }
.tl-video-track::before { right: 0; background: var(--tl-media-rest); opacity: 0.18; }
.tl-video-fill { width: var(--at, 0%); background: var(--tl-media-played); }
.tl-video-track .tl-audio-head { top: 2px; bottom: 2px; }
.tl-video-track:hover::before { opacity: 0.28; }
@container (max-width: 400px) {
  .tl-video .tl-audio-row { flex-wrap: wrap; }
  .tl-video .tl-audio-meta { order: -2; flex: 1 0 100%; margin: 0 0 var(--space-8); }
}

/* A video inside a gallery is a perfect square like the pictures: the picture fills it and a slim control strip
   (play, title, CC, sound, full screen, scrubber, times) sits over the bottom on a soft shade. */
.tl-gallery-track { overflow-y: hidden; }
.tl-gallery-slide > .tl-video {
  display: grid; grid-template-rows: 1fr auto auto auto; gap: 0; align-self: stretch;
  position: relative; max-width: none; aspect-ratio: 1; padding: 0; overflow: hidden;
  border-radius: 0; background: var(--color-neutral-900); box-shadow: none; color: var(--color-neutral-50);
  --tl-media-rest: var(--color-neutral-50); --tl-media-softer: rgb(255 255 255 / 0.22); --tl-media-soft: rgb(255 255 255 / 0.14);
}
.tl-gallery-slide > .tl-video .tl-video-frame { grid-area: 1 / 1 / -1 / 2; position: absolute; inset: 0; border-radius: 0; }
.tl-gallery-slide > .tl-video video { width: 100%; height: 100%; object-fit: contain; }
.tl-gallery-slide > .tl-video .tl-video-frame::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 38%; pointer-events: none;
  background: linear-gradient(to top, rgb(0 0 0 / 0.72), transparent); }
.tl-gallery-slide > .tl-video .tl-audio-row, .tl-gallery-slide > .tl-video .tl-video-track, .tl-gallery-slide > .tl-video .tl-media-time { position: relative; z-index: 2; margin-left: var(--space-16); margin-right: var(--space-16); }
.tl-gallery-slide > .tl-video .tl-audio-row { grid-row: 2; flex-wrap: nowrap; margin-top: 0; gap: var(--space-8); }
.tl-gallery-slide > .tl-video .tl-video-track { grid-row: 3; }
.tl-gallery-slide > .tl-video .tl-media-time { grid-row: 4; margin-bottom: var(--space-12); color: rgb(255 255 255 / 0.75); }
.tl-gallery-slide > .tl-video .tl-audio-row > .tl-media-btn { display: none; }
.tl-gallery-slide > .tl-video .tl-media-btn { color: rgb(255 255 255 / 0.85); }
.tl-gallery-slide > .tl-video .tl-media-btn:hover { color: #fff; }
.tl-gallery-slide > .tl-video .tl-media-play { width: 44px; height: 44px; }
.tl-gallery-slide > .tl-video .tl-audio-meta { order: 0; flex: 1 1 auto; margin: 0 0 0 var(--space-8); }
.tl-gallery-slide > .tl-video .tl-audio-kicker { display: none; }
.tl-gallery-slide > .tl-video .tl-audio-title { color: #fff; font-size: 15px; text-shadow: 0 1px 6px rgb(0 0 0 / 0.5); }
.tl-gallery-slide > .tl-video .tl-media-tools { padding-left: 0; }
.tl-gallery-slide > .tl-video .tl-video-frame > .tl-provenance { top: var(--space-12); bottom: auto; transform-origin: right top; }
.tl-gallery-slide > .tl-video .tl-audio-wave:focus-visible, .tl-gallery-slide > .tl-video .tl-video-track:focus-visible { outline-color: #fff; }

.tl-gallery-slide > .tl-video .tl-audio-row, .tl-gallery-slide > .tl-video .tl-video-track, .tl-gallery-slide > .tl-video .tl-media-time, .tl-gallery-slide > .tl-video .tl-video-frame::after {
  transition: opacity var(--dur-base) var(--ease-out); }
.tl-gallery-slide > .tl-video.is-idle .tl-audio-row, .tl-gallery-slide > .tl-video.is-idle .tl-video-track, .tl-gallery-slide > .tl-video.is-idle .tl-media-time { opacity: 0; pointer-events: none; }
.tl-gallery-slide > .tl-video.is-idle .tl-video-frame::after { opacity: 0; }
.tl-gallery-slide > .tl-video.is-idle video { cursor: none; }

@media (prefers-reduced-motion: reduce) {
  .tl-media-btn, .tl-media-play, .tl-audio-wave i, .tl-audio-caption, .tl-gallery-slide > .tl-video .tl-audio-row, .tl-gallery-slide > .tl-video .tl-video-track, .tl-gallery-slide > .tl-video .tl-media-time, .tl-gallery-slide > .tl-video .tl-video-frame::after { transition: none; }
  .tl-media-play:active { transform: none; }
}

/* ---------- Product gallery: big picture with arrows and swipe, thumbnails below with their own arrows ---------- */
.tl-gallery { --tl-gal-gap: var(--space-8); display: grid; gap: var(--tl-gal-gap); min-width: 0; }
.tl-gallery-stage { position: relative; }
.tl-gallery-track { display: flex; align-items: flex-start; transition: height var(--dur-base) var(--ease-out); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior-x: contain; border-radius: var(--radius-md); }
.tl-gallery-track::-webkit-scrollbar, .tl-gallery-thumbs::-webkit-scrollbar { display: none; }
.tl-gallery-slide { flex: 0 0 100%; min-width: 0; scroll-snap-align: center; margin: 0; display: grid; align-items: start; align-self: flex-start; }
.tl-gallery-slide > img { display: block; width: 100%; height: auto; }
.tl-gallery-arrow { position: absolute; top: 50%; z-index: 2; width: 44px; height: 44px; margin-top: -22px; display: grid; place-items: center; padding: 0; border: 0; cursor: pointer;
  border-radius: var(--radius-sm); background: var(--color-bg-inverse); color: var(--color-text-inverse); opacity: 0.92;
  transition: background var(--dur-quick) var(--ease-out), opacity var(--dur-quick) var(--ease-out), transform var(--dur-quick) var(--ease-out); }
.tl-gallery-arrow svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.tl-gallery-arrow:hover { opacity: 1; }
.tl-gallery-arrow:active { transform: translateY(1px); }
.tl-gallery-arrow:focus-visible, .tl-gallery-thumb:focus-visible { outline: 2px solid var(--color-border-focus, currentColor); outline-offset: 2px; }
.tl-gallery-arrow[disabled] { opacity: 0; pointer-events: none; }
.tl-gallery-prev { left: var(--space-12); } .tl-gallery-next { right: var(--space-12); }
.tl-gallery-count { position: absolute; left: var(--space-12); top: var(--space-12); z-index: 2; font: var(--text-label-s); font-variant-numeric: tabular-nums;
  padding: 2px var(--space-8); border-radius: var(--radius-sm); background: var(--color-bg-inverse); color: var(--color-text-inverse); pointer-events: none; }
.tl-gallery-strip { position: relative; }
.tl-gallery-thumbs { display: flex; gap: var(--tl-gal-gap); overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none; }
.tl-gallery-thumb { flex: 0 0 calc((100% - 3 * var(--tl-gal-gap)) / 4); aspect-ratio: 1; padding: 0; border: 0; cursor: pointer; overflow: hidden; scroll-snap-align: start;
  border-radius: var(--radius-sm); background: var(--color-neutral-900); opacity: 0.6; transition: opacity var(--dur-quick) var(--ease-out); }
.tl-gallery-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tl-gallery-thumb:hover { opacity: 0.85; }
.tl-gallery-thumb[aria-current="true"] { opacity: 1; box-shadow: inset 0 0 0 2px var(--color-text-primary); }
.tl-gallery-strip .tl-gallery-arrow { width: 32px; height: 32px; margin-top: -16px; }
.tl-gallery-strip .tl-gallery-arrow svg { width: 16px; height: 16px; }
.tl-gallery-strip .tl-gallery-prev { left: var(--space-4); } .tl-gallery-strip .tl-gallery-next { right: var(--space-4); }
@media (prefers-reduced-motion: reduce) { .tl-gallery-arrow, .tl-gallery-thumb { transition: none; } .tl-gallery-track, .tl-gallery-thumbs { scroll-behavior: auto; } .tl-gallery-track { transition: none; } }

/* ---------- Animated logo ----------
   Rebuilt from the tomatolab.org SVGator animation: the circle and square draw
   as single strokes (1.5s), and the wordmark wipes in left to right (0.3s to 1.5s).
   Use with the inline SVG from assets/logos/animated.svg. Add .is-replaying
   briefly (or re-insert the SVG) to play it again. */
.tl-logo-draw .la-stroke {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: tl-logo-draw 1.5s cubic-bezier(0.39, 0.575, 0.565, 1) forwards;
}
.tl-logo-draw .la-word {
  clip-path: inset(0 100% 0 0);
  animation: tl-logo-wipe 1.2s cubic-bezier(0.39, 0.575, 0.565, 1) 0.3s forwards;
}
@keyframes tl-logo-draw { to { stroke-dashoffset: 0; } }
@keyframes tl-logo-wipe { to { clip-path: inset(0 0 0 0); } }
@media (prefers-reduced-motion: reduce) {
  .tl-logo-draw .la-stroke, .tl-logo-draw .la-word { animation: none; stroke-dashoffset: 0; clip-path: none; }
}

/* Inputs and selection controls ease between states */
.tl-input, .tl-checkbox, .tl-radio, .tl-toggle { transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out); }
@media (prefers-reduced-motion: reduce) {
  .tl-button, .tl-input, .tl-checkbox, .tl-radio, .tl-toggle, .tl-toggle::before { transition: none; }
  .tl-button:active:not(:disabled) { transform: none; }
}
