/* ---------- Installation Queue ----------
   Layered on popup.css, which already supplies the overlay, the window, the
   rise animation and the reduced-motion opt-out. Only what is specific to the
   queue lives here.

   The design brief was calm and software-focused rather than commercial —
   Apple, Arc, Raycast, Linear, Craft. In practice that means: more air than
   feels necessary, hairline dividers instead of boxes, one accent and no
   second color, type that steps down in size rather than shouting, and
   motion measured in a sixth of a second. Nothing here bounces. */

.queue-win { max-width: 460px; }
.queue-close { top: 46px; right: 14px; }

/* august.css styles the bare `footer` element — border-top plus a clamped
   margin-top for the page footer — and this dialog uses <footer> too, so it
   inherited a 50px gap above the total. Exactly the trap the .follow-* bug
   was: markup borrowing a name the page already owns.
   Reset rather than rename, because <footer> IS the right element here and
   the semantics are worth more than the collision costs. */
.queue-head, .queue-foot { margin: 0; }

.queue-grabber { display: none; }

/* ---------- head ---------- */

.queue-head {
  padding: clamp(1.7rem, 5vw, 2.1rem) clamp(1.4rem, 5vw, 1.9rem) 1.1rem;
}
.queue-title {
  font-size: clamp(1.5rem, 4.4vw, 1.8rem);
  line-height: 1.1;
  margin: 0 0 .35rem;
  letter-spacing: -.015em;
}
.queue-sub {
  margin: 0;
  font-size: .74rem;
  letter-spacing: .04em;
  color: var(--text-faint);
}

/* ---------- the queue ---------- */

/* One scrolling body, so the head scrolls away with the list on a phone
   instead of eating a third of a short screen. */
.queue-scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  max-height: min(62vh, 30rem);
}

.queue-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.queue-item {
  display: grid;
  grid-template-columns: 54px 1fr auto;
  align-items: center;
  gap: .95rem;
  padding: .85rem clamp(1.4rem, 5vw, 1.9rem);
  position: relative;
  transition: background-color .18s ease;
}
.queue-item + .queue-item::before {
  content: "";
  position: absolute;
  left: clamp(1.4rem, 5vw, 1.9rem); right: clamp(1.4rem, 5vw, 1.9rem); top: 0;
  height: 1px;
  background: var(--border);
}
.queue-item:hover { background: var(--surface-2); }

/* arriving: the row settles in rather than appearing */
@keyframes queue-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.queue-item { animation: queue-in .3s cubic-bezier(.22, .61, .36, 1) both; }
/* a short stagger, so a queue of three settles rather than snapping */
.queue-item:nth-child(2) { animation-delay: .04s; }
.queue-item:nth-child(3) { animation-delay: .08s; }
.queue-item:nth-child(n+4) { animation-delay: .12s; }

/* leaving: collapse to nothing so the rows below close the gap smoothly */
.queue-item.is-going {
  animation: none;
  opacity: 0;
  transform: translateX(10px);
  transition: opacity .16s ease, transform .16s ease;
}

/* The artwork. An icon rather than a screenshot on purpose: at 54px a hero
   image is mush, and the icon IS how an application identifies itself at this
   size — which is what macOS's own installer shows. It is given real presence
   (a tinted bed, a soft shadow, a hairline) so it reads as artwork rather
   than a bullet point. */
.queue-art {
  position: relative;
  width: 54px; height: 54px;
  border-radius: 13px;
  display: grid; place-items: center;
  background: var(--accent-soft);
  flex: none;
}
.queue-art::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(15, 17, 22, .05);
  pointer-events: none;
}
.queue-icon {
  width: 42px; height: 42px;
  border-radius: 10px;
  display: block;
  box-shadow: 0 1px 2px rgba(15, 17, 22, .14), 0 5px 12px rgba(15, 17, 22, .10);
}

.queue-meta { min-width: 0; }
.queue-name {
  display: flex; align-items: baseline; gap: .45rem;
  font-size: .95rem; font-weight: 600; letter-spacing: -.005em;
  color: var(--text);
  margin: 0 0 .12rem;
}
.queue-version {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .64rem; font-weight: 500;
  letter-spacing: .03em;
  color: var(--text-faint);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: .07rem .3rem;
  flex: none;
}
.queue-tagline {
  margin: 0 0 .22rem;
  font-size: .78rem; line-height: 1.35;
  color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* What an installer tells you before it installs: how big, what it needs. */
.queue-facts {
  margin: 0;
  display: flex; align-items: center; flex-wrap: wrap;
  gap: .3rem .45rem;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .64rem; letter-spacing: .02em;
  color: var(--text-faint);
}
.queue-facts span + span::before {
  content: "·";
  margin-right: .45rem;
  opacity: .65;
}

.queue-right { display: flex; align-items: center; gap: .55rem; }
/* Deliberately NOT bold and NOT full-contrast. A heavy, dark, right-aligned
   number in a column reads as a line total on an invoice; the same number set
   quietly reads as a fact about the application, which is what the App Store
   does and what this is. */
.queue-price {
  font-size: .82rem; font-weight: 500;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

.queue-remove {
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
  opacity: 0;
  transition: opacity .16s ease, color .16s ease, border-color .16s ease, background-color .16s ease;
}
.queue-remove svg { width: 13px; height: 13px; }
.queue-item:hover .queue-remove,
.queue-remove:focus-visible { opacity: 1; }
.queue-remove:hover {
  color: var(--text);
  border-color: var(--border);
  background: var(--bg);
}
/* Touch has no hover, so the control must simply be there — but quietly. A
   row of prominent delete buttons is a cart; a faint one is an affordance. */
@media (hover: none) { .queue-remove { opacity: .45; } }

/* ---------- empty ---------- */

.queue-empty {
  padding: .4rem clamp(1.4rem, 5vw, 1.9rem) clamp(1.9rem, 5vw, 2.3rem);
  text-align: center;
}
.queue-empty-mark {
  width: 42px; height: 42px;
  margin: .5rem auto 1rem;
  display: grid; place-items: center;
  border-radius: 12px;
  border: 1px solid var(--border);
  color: var(--text-faint);
}
.queue-empty-mark svg { width: 20px; height: 20px; }
.queue-empty-title {
  margin: 0 0 .3rem;
  font-size: .95rem; font-weight: 600; color: var(--text);
}
.queue-empty-copy {
  margin: 0 0 1.15rem;
  font-size: .84rem; color: var(--text-muted);
}
.queue-empty-link {
  font-size: .84rem; font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
.queue-empty-link span { display: inline-block; transition: transform .18s ease; }
.queue-empty-link:hover span { transform: translateX(3px); }

/* ---------- foot ---------- */

.queue-foot {
  border-top: 1px solid var(--border);
  margin-top: 0;
  padding: 1.05rem clamp(1.4rem, 5vw, 1.9rem) clamp(1.4rem, 5vw, 1.7rem);
  background: var(--surface-2);
  border-radius: 0 0 inherit inherit;
}
.queue-confirm { margin-bottom: .7rem; }
.queue-confirm-line {
  margin: 0 0 .12rem;
  font-size: .95rem; font-weight: 600; letter-spacing: -.005em;
  color: var(--text);
}
.queue-confirm-meta {
  margin: 0;
  font-size: .68rem; letter-spacing: .03em;
  color: var(--text-faint);
}

.queue-summary {
  display: flex; align-items: baseline; justify-content: space-between;
  padding-top: .7rem;
  margin-bottom: .9rem;
  border-top: 1px solid var(--border);
}
.queue-summary-label {
  font-size: .7rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-faint);
}
.queue-summary-value {
  font-size: 1.32rem; font-weight: 600; letter-spacing: -.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.queue-install {
  width: 100%;
  justify-content: center;
  position: relative;
}
.queue-install.is-busy { pointer-events: none; }
.queue-install.is-busy .queue-install-label { opacity: .45; }
.queue-install.is-busy .queue-spinner { opacity: 1; }

.queue-spinner {
  position: absolute;
  right: 1.1rem; top: 50%;
  width: 14px; height: 14px;
  margin-top: -7px;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff;
  border-radius: 50%;
  opacity: 0;
  transition: opacity .16s ease;
  animation: queue-spin .7s linear infinite;
}
@keyframes queue-spin { to { transform: rotate(360deg); } }

.queue-fineprint {
  margin: .8rem 0 0;
  text-wrap: balance;
  text-align: center;
  font-size: .68rem; letter-spacing: .03em;
  color: var(--text-faint);
}
.queue-msg { text-align: center; margin-top: .55rem; }

/* ---------- the header control ---------- */

.basket-btn { position: relative; }
.basket-count {
  position: absolute;
  top: -3px; right: -3px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .6rem; font-weight: 600; line-height: 16px;
  text-align: center;
  transform: scale(0);
  transition: transform .22s cubic-bezier(.34, 1.56, .64, 1);
  pointer-events: none;
}
.basket-count.on { transform: scale(1); }

/* the icon acknowledges an addition, so the click has somewhere to land */
@keyframes basket-nudge {
  0%, 100% { transform: none; }
  35%      { transform: translateY(-3px) scale(1.06); }
}
.basket-btn.is-added { animation: basket-nudge .34s cubic-bezier(.34, 1.3, .64, 1); }

/* ---------- the queue action, next to Install ----------
   It was 105x20px of gray mono text wedged between two full-size buttons,
   which is why it read as decoration rather than a control. It is now a peer
   of the other two actions — same height, same shape, same type scale — but
   deliberately the quietest of the three: Install is filled, this is outlined
   in the accent, the Inspector is a plain ghost. Second in the hierarchy,
   not second-class. */

.btn-queue {
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--accent-soft);
  border: 1px solid var(--accent-ring);
  color: var(--accent);
  cursor: pointer;
  transition: background-color .18s ease, border-color .18s ease,
              color .18s ease, transform .12s ease;
}
.btn-queue:hover {
  background: var(--accent-ring);
  border-color: var(--accent);
}
.btn-queue:active { transform: scale(.985); }

.queue-plus {
  display: grid; place-items: center;
  width: 17px; height: 17px;
  border-radius: 5px;
  background: var(--accent);
  color: #fff;
  flex: none;
  transition: transform .2s cubic-bezier(.34, 1.4, .64, 1);
}
.queue-plus svg { width: 11px; height: 11px; }
.btn-queue:hover .queue-plus { transform: rotate(90deg); }

/* Already queued: it stops offering and starts reporting. The plus becomes a
   tick, and the button reads as a state rather than an action — but stays
   clickable, because the useful thing then is to open the queue. */
.btn-queue[data-state="added"] {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text-muted);
}
.btn-queue[data-state="added"] .queue-plus {
  background: var(--ok, #1F9D55);
  transform: none;
}
.btn-queue[data-state="added"]:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- the icon flying to the queue ----------
   The one piece of motion that actually explains what happened: the
   application leaves the button and lands on the header control. It answers
   "where did it go" without a word of copy, which is the whole problem the
   old design had. */
.queue-flight {
  position: fixed;
  width: 38px; height: 38px;
  border-radius: 9px;
  z-index: 120;
  pointer-events: none;
  box-shadow: 0 6px 20px rgba(15, 17, 22, .22);
  transition: transform .58s cubic-bezier(.55, -0.05, .6, 1), opacity .58s ease;
}

/* ---------- the one-sentence explanation, once ---------- */
.queue-toast {
  position: fixed;
  right: clamp(12px, 3vw, 22px);
  top: 74px;
  z-index: 110;
  width: min(310px, calc(100vw - 24px));
  padding: .85rem 1rem .9rem;
  border-radius: 13px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-float);
  opacity: 0;
  transform: translateY(-8px) scale(.98);
  transition: opacity .26s ease, transform .26s cubic-bezier(.22, .61, .36, 1);
  pointer-events: none;
}
.queue-toast.on { opacity: 1; transform: none; }
.queue-toast-title {
  margin: 0 0 .18rem;
  font-size: .82rem; font-weight: 600; color: var(--text);
}
.queue-toast-copy {
  margin: 0;
  font-size: .76rem; line-height: 1.45; color: var(--text-muted);
}

@media (max-width: 600px) {
  .queue-toast { top: auto; bottom: 16px; right: 12px; left: 12px; width: auto; }
  .queue-toast { transform: translateY(10px) scale(.98); }
  .queue-toast.on { transform: none; }
  .btn-queue { width: 100%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .queue-flight { display: none; }
  .queue-toast, .btn-queue, .queue-plus { transition: none; }
}

@media (prefers-reduced-motion: reduce) {
  .queue-item, .basket-btn.is-added, .queue-spinner { animation: none; }
  .basket-count { transition: none; }
}

/* ============================================================
   THE INSTALLATION SHEET — phones
   ============================================================

   Not the desktop dialog made smaller. A centered modal is a desktop idea: it
   assumes a pointer, a big screen, and that the thing behind it stays useful.
   On a phone the native gesture is a sheet that rises from the bottom edge,
   sits under the thumb, and can be thrown back down — Apple Music, Maps, the
   share sheet. So that is what this becomes.

   What survives the change is the identity: still a macOS window, still the
   traffic lights, still the mono title. It reads as an August application
   that knows it is on a phone, rather than a website pretending to be an app.
   ============================================================ */

@media (max-width: 600px) {
  .queue-pop {
    align-items: flex-end;
    padding: 0;
  }

  .queue-win {
    max-width: none;
    width: 100%;
    /* Corners only at the top: it is attached to the bottom edge, not
       floating. Anything else looks like a card that fell down the screen. */
    border-radius: 20px 20px 0 0;
    /* Never taller than the screen, never so short it looks stranded. */
    max-height: 92vh;
    display: flex;
    flex-direction: column;
    animation: sheet-rise .34s cubic-bezier(.32, .72, 0, 1) both;
    /* the sheet is dragged by JS; keep that instant while it is happening */
    will-change: transform;
  }
  .queue-win.is-dragging { animation: none; transition: none; }
  .queue-win.is-settling { transition: transform .26s cubic-bezier(.32, .72, 0, 1); }

  @keyframes sheet-rise {
    from { transform: translateY(100%); }
    to   { transform: none; }
  }

  /* The grab handle. The affordance that says "you can throw this away",
     which on touch does the job the close button does with a pointer. */
  .queue-grabber {
    display: block;
    padding: 9px 0 3px;
    text-align: center;
    cursor: grab;
    touch-action: none;
  }
  .queue-grabber span {
    display: inline-block;
    width: 38px; height: 4px;
    border-radius: 2px;
    background: var(--border-strong);
    opacity: .8;
  }

  /* The title bar stays — this is still a window — but it gives up the
     vertical space it was taking. */
  .win-bar { padding-top: 2px; padding-bottom: 6px; }

  .queue-close { top: 40px; right: 10px; }

  .queue-scroll {
    max-height: none;
    flex: 1 1 auto;
    min-height: 0;
  }

  .queue-head { padding-top: 1.1rem; padding-bottom: .85rem; }
  .queue-title { font-size: 1.55rem; }

  /* Rows get taller: a 44px target is the floor for a thumb. */
  .queue-item { padding-top: 1rem; padding-bottom: 1rem; }
  .queue-tagline {
    white-space: normal;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  }
  .queue-remove { width: 40px; height: 40px; border-radius: 10px; }
  .queue-remove svg { width: 15px; height: 15px; }

  /* The footer is pinned so the action is always under the thumb, and it
     clears the home indicator rather than sitting behind it. */
  .queue-foot {
    flex: none;
    padding-bottom: calc(1.15rem + env(safe-area-inset-bottom, 0px));
  }
  .queue-install { padding-top: .95rem; padding-bottom: .95rem; font-size: 1rem; }

  /* Tap feedback, since there is no hover to give any. */
  .queue-install:active { transform: scale(.985); }
  .queue-item:active { background: var(--surface-2); }
}

/* Very short screens — a phone in landscape. The sheet would otherwise be all
   chrome and no content. */
@media (max-width: 600px) and (max-height: 460px) {
  .queue-win { max-height: 96vh; border-radius: 14px 14px 0 0; }
  .queue-head { padding-top: .8rem; padding-bottom: .6rem; }
  .queue-title { font-size: 1.25rem; }
  .queue-grabber { padding: 6px 0 2px; }
}

@media (prefers-reduced-motion: reduce) {
  .queue-win { animation: none; }
}

/* ── the waiver ─────────────────────────────────────────────────────────
   The last thing read before the Install button, and deliberately not
   fine print: it is the sentence that decides whether a change of mind is
   refundable, so it is set at the same size as the confirmation line
   above it rather than tucked under it.

   Not accented, not colored, no icon. It is a statement to read, and
   dressing it up as a feature would be the wrong kind of persuasion for
   the one control on this panel that takes a right away. */

.queue-waiver {
  display: flex;
  gap: .6rem;
  align-items: flex-start;
  margin: 0 0 .85rem;
  cursor: pointer;
}
.queue-waiver-box {
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  margin: .12rem 0 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.queue-waiver-text {
  font-size: .82rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.queue-waiver:hover .queue-waiver-text { color: var(--text); }
.queue-waiver-box:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
