/* ==========================================================================
   File result card — 1 August 2026
   Upload → convert → download tools ended on a status pill with the file
   already gone to the downloads folder. This card reports the produced file and
   offers it again. It is a standalone element inserted after the tool status
   line, so it never competes with the shared result box for the same node.
   ========================================================================== */

/* The card reports the whole run — progress, result and failures — so the
   status pills are retired on these tools. They sat at the bottom of the form,
   which on a tall tool put the message off screen exactly when it mattered.
   Everything they said now appears on the card; they stay in the accessibility
   tree so screen readers still announce them. */
/* Beats the sitewide inline-notice rule in site.css, which is scoped to the
   same depth plus :not(:empty). The :has() test keeps this to pages where the
   card actually mounted — anywhere else the status line is still the only
   messenger and must stay visible. */
body[data-tool] .tool-form:has(.ttg-file-card) .tool-status:not(:empty),
body[data-tool] .tool-form:has(.ttg-file-card) .tool-status,
body[data-tool] .tool-form:has(.ttg-file-card) #toolFields .tool-status,
body[data-tool] .tool-form:has(.ttg-file-card) #suiteStatus,
body[data-tool] .tool-form:has(.ttg-file-card) #megaStatus {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  min-height: 0 !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.ttg-file-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  margin-top: 14px;
  padding: 22px 16px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 8px 22px rgba(34, 43, 38, .05);
}

.ttg-file-card[hidden] {
  display: none !important;
}

/* The card is shown and hidden through the hidden attribute. Transitioning
   display (even with allow-discrete) left it rendered while hidden, so the
   entrance is a keyframe animation and the exit is a class the script sets
   just before hiding. */
/* No fill mode on purpose: if the animation never ticks (background tab, a
   renderer that is not compositing), the card falls back to its resting style
   and is simply visible, rather than being stuck on the transparent first
   keyframe. */
.ttg-file-card:not([hidden]) {
  animation: ttg-card-in .26s cubic-bezier(.2, .7, .3, 1);
}

.ttg-file-card.is-leaving {
  animation: none;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease;
}

@keyframes ttg-card-in {
  from { opacity: 0; transform: translateY(-7px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ttg-file-card:not([hidden]) { animation: none; }
  .ttg-file-card.is-leaving { transition: none; }
}

/* site.css orders the form's children (result box, status, then the rest); the
   card leads so the message is the first thing on screen, with the result
   itself still visible underneath. */
body[data-tool] .tool-form > .ttg-file-card,
.tool-form > .ttg-file-card {
  order: 0;
}

/* Only the finished-file card replaces the result box — it already restates the
   headline and details. A notice (copied, working, failed) says something the
   result box does not, so the result stays on screen underneath it. Done with
   :has() so nothing has to mutate the box. */
.tool-form:has(.ttg-file-card[data-state="ready"]:not([hidden])) #resultBox {
  display: none !important;
}

.ttg-file-card__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--teal-soft);
  color: var(--teal);
  font-size: 1.15rem;
}

.ttg-file-card__copy {
  min-width: 0;
}

.ttg-file-card__title {
  display: block;
  color: var(--ink);
  font-family: "Plus Jakarta Sans", Manrope, sans-serif;
  font-size: 1.02rem;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -.025em;
}

.ttg-file-card__meta {
  margin: 2px 0 0;
  color: var(--muted);
  font-size: .76rem;
  font-weight: 650;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.ttg-file-card__meta:empty {
  display: none;
}

/* ---- Working and failed states ---------------------------------------- */

.ttg-file-card__icon-busy,
.ttg-file-card__icon-failed,
.ttg-file-card__icon-warn,
.ttg-file-card__bar {
  display: none;
}

/* A notice is one line of message with no file attached, so it uses a shorter
   panel than the download card. */
.ttg-file-card[data-state="done"],
.ttg-file-card[data-state="warning"],
.ttg-file-card[data-state="error"],
.ttg-file-card[data-state="busy"] {
  gap: 11px;
  padding: 11px 14px;
}

.ttg-file-card[data-state="done"] .ttg-file-card__icon,
.ttg-file-card[data-state="warning"] .ttg-file-card__icon,
.ttg-file-card[data-state="error"] .ttg-file-card__icon,
.ttg-file-card[data-state="busy"] .ttg-file-card__icon {
  width: 30px;
  height: 30px;
  font-size: .95rem;
}

.ttg-file-card[data-state="done"] .ttg-file-card__download,
.ttg-file-card[data-state="warning"] .ttg-file-card__download {
  display: none;
}

.ttg-file-card[data-state="done"] .ttg-file-card__title,
.ttg-file-card[data-state="warning"] .ttg-file-card__title,
.ttg-file-card[data-state="busy"] .ttg-file-card__title {
  font-size: .92rem;
  font-weight: 750;
  line-height: 1.5;
  letter-spacing: 0;
}

.ttg-file-card[data-state="warning"] {
  border-color: color-mix(in srgb, var(--brand) 30%, var(--line));
  background: color-mix(in srgb, var(--surface) 94%, var(--brand));
}

.ttg-file-card[data-state="warning"] .ttg-file-card__icon {
  background: color-mix(in srgb, var(--brand) 13%, var(--surface));
  color: var(--brand);
}

.ttg-file-card[data-state="warning"] .ttg-file-card__icon-done {
  display: none;
}

.ttg-file-card[data-state="warning"] .ttg-file-card__icon-warn {
  display: block;
}

.ttg-file-card[data-state="error"] {
  border-color: color-mix(in srgb, var(--danger) 32%, var(--line));
  background: color-mix(in srgb, var(--surface) 94%, var(--danger));
}

.ttg-file-card[data-state="error"] .ttg-file-card__icon {
  background: color-mix(in srgb, var(--danger) 13%, var(--surface));
  color: var(--danger);
}

.ttg-file-card[data-state="error"] .ttg-file-card__icon-done {
  display: none;
}

.ttg-file-card[data-state="error"] .ttg-file-card__icon-failed {
  display: block;
}

.ttg-file-card[data-state="error"] .ttg-file-card__title {
  font-size: .92rem;
  font-weight: 750;
  line-height: 1.5;
  letter-spacing: 0;
}

.ttg-file-card[data-state="error"] .ttg-file-card__download {
  display: none;
}

.ttg-file-card[data-state="busy"] .ttg-file-card__icon {
  background: color-mix(in srgb, var(--brand) 12%, var(--surface));
  color: var(--brand);
}

.ttg-file-card[data-state="busy"] .ttg-file-card__icon-done {
  display: none;
}

.ttg-file-card[data-state="busy"] .ttg-file-card__icon-busy {
  display: block;
  animation: ttg-file-spin 1s linear infinite;
}

.ttg-file-card[data-state="busy"] .ttg-file-card__download {
  display: none;
}

/* The bar carries the site's own .skeleton class, so the shimmer here is the
   same loading treatment used elsewhere on the site. */
.ttg-file-card[data-state="busy"] .ttg-file-card__bar {
  display: block;
  height: 6px;
  margin-top: 10px;
  border-radius: 999px;
}

@keyframes ttg-file-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .ttg-file-card__icon-busy {
    animation: none !important;
  }
}

.ttg-file-card__download {
  min-width: 0;
  min-height: 40px;
  padding-inline: 18px;
  border-radius: 12px;
  font-size: .84rem;
  white-space: nowrap;
}

[data-theme="dark"] .ttg-file-card {
  border-color: var(--line);
  background: var(--surface);
}

@media (max-width: 700px) {
  .ttg-file-card {
    grid-template-columns: auto minmax(0, 1fr);
    gap: 12px;
    padding: 12px 14px;
  }

  .ttg-file-card__download {
    grid-column: 1 / -1;
    width: 100%;
  }
}

@media (max-width: 380px) {
  .ttg-file-card {
    grid-template-columns: 1fr;
  }

  .ttg-file-card__icon {
    width: 36px;
    height: 36px;
    font-size: 1rem;
  }
}

/* An upload the tool cannot use is marked at the control itself, with the card
   sitting directly above it. */
/* The enhanced dropzone paints a gradient through background-image, so the
   longhands are set rather than the shorthand. */
.ttg-upload-invalid {
  border-color: color-mix(in srgb, var(--danger) 42%, var(--line)) !important;
  background-image: none !important;
  background-color: rgba(201, 79, 89, .09) !important;
  /* The dropzone's own background-color stays transparent — its surface is
     painted with gradients through background-image, and something in the
     cascade keeps the colour layer clear. The inset shadow washes the panel
     regardless of how its background is built. */
  box-shadow:
    inset 0 0 0 999px rgba(201, 79, 89, .09),
    0 0 0 3px rgba(201, 79, 89, .11) !important;
}

.ttg-upload-invalid::before,
.ttg-upload-invalid::after {
  opacity: 0 !important;
}

.ttg-upload-invalid .file-upload-icon,
.ttg-upload-invalid > i {
  color: var(--danger) !important;
}

.ttg-file-card + .ttg-upload-invalid,
.ttg-upload-invalid {
  transition: border-color .2s ease, background .2s ease, box-shadow .2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .ttg-upload-invalid { transition: none; }
}
