/* ──────────────────────────────────────────────────────────────────────────
   apps.css — the app registry page (#apps) and the embedded-tool host.

   Everything here is scoped to `.reg-grid` (the registry's own grid) or the
   `af-`/`pick-` prefixes, never to bare `.app-card`/`.app-grid`: the dashboard
   tile and the art wall borrow those same classes at frozen heights, and a rule
   written for this page would silently reflow theirs.

   Note on shadows: theme.css defines --shadow-sm/md/lg as `var(--shadow-sm)`
   (self-referential), so every box-shadow:var(--shadow-*) in the app computes to
   none. Shadows here are written out literally rather than inheriting that bug.
   ────────────────────────────────────────────────────────────────────────── */

/* ── registry header: the one-line health summary + recheck ── */
.reg-side{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap}
.reg-sum{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-small);color:var(--text-dim)}
.reg-dot{width:7px;height:7px;border-radius:50%;background:var(--text-faint);flex:0 0 auto}
.reg-sum[data-s="checking"] .reg-dot{animation:reg-pulse 1.3s var(--ease) infinite}
.reg-sum[data-s="ok"] .reg-dot{background:var(--success)}
.reg-sum[data-s="down"]{color:var(--danger)}
.reg-sum[data-s="down"] .reg-dot{background:var(--danger)}
@keyframes reg-pulse{0%,100%{opacity:.25}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.reg-sum[data-s="checking"] .reg-dot{animation:none;opacity:.6}}

/* ── the grid ── */
.reg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(216px,1fr));gap:var(--sp-3)}

/* The card is an <a href="#app:slug">: Tab reaches it, Enter opens it, and
   ⌘/ctrl/middle-click opens the platform at that app in a new browser tab.
   Before this it was a <div onclick> — unreachable from a keyboard entirely. */
.reg-grid .app-card{
  display:flex;flex-direction:column;color:inherit;text-decoration:none;
  padding:15px 15px 13px;position:relative;min-height:180px;
}
.reg-grid .app-card:hover{text-decoration:none;box-shadow:0 6px 18px rgba(0,0,0,.32)}
.reg-grid .app-card:hover .app-ico{color:var(--accent-2);transform:scale(1.04)}
.reg-grid .app-ico{
  width:40px;height:40px;border-radius:10px;font-size:20px;margin-bottom:11px;
  transition:transform var(--dur-fast) var(--ease),color var(--dur-fast);
}
.reg-grid .a-body{flex:1;min-width:0;display:flex;flex-direction:column}
.reg-grid .a-name{font-size:var(--fs-body);line-height:1.25;margin-bottom:4px}
.reg-grid .a-desc{font-size:var(--fs-tiny);min-height:0;margin-bottom:10px}

/* Meta rides the bottom edge so cards in a row line their footers up even when
   descriptions run to different lengths. */
.reg-grid .a-meta{margin-top:auto;display:flex;align-items:center;gap:7px;min-width:0}
.reg-grid .a-kind{margin-top:0;flex:0 0 auto}
.a-mount{
  font-family:var(--font-mono);font-size:var(--fs-micro);color:var(--text-faint);
  background:var(--bg-base);border:1px solid var(--border);border-radius:5px;
  padding:2px 6px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.reg-grid .a-flags{margin-left:0;margin-top:9px}
.pill.a-access{background:var(--teal-glow);color:var(--teal)}

/* Only a tool that is NOT answering earns a colour. Five green ticks would be
   decoration; one red line is information. */
.a-down{
  display:flex;align-items:center;gap:6px;margin-top:9px;
  font-size:var(--fs-tiny);font-weight:600;color:var(--danger);
}
.a-down::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--danger);flex:0 0 auto}

/* Register card: a real <button>, same silhouette as the cards beside it. */
.reg-grid .reg-add{
  font:inherit;text-align:center;width:100%;color:var(--text-faint);
  align-items:center;justify-content:center;gap:6px;
  border-style:dashed;
}
.reg-grid .reg-add:hover{color:var(--accent);border-color:var(--accent)}
.reg-grid .reg-plus{font-size:22px;line-height:1}

/* Loading: card-shaped, so the grid doesn't jump when the data lands. */
.reg-grid .reg-skel{background:var(--bg-surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:15px;min-height:180px;display:flex;flex-direction:column;gap:9px}
.reg-grid .skel-block{width:40px;height:40px;border-radius:10px;flex:0 0 auto}
.reg-grid .skel-col{display:flex;flex-direction:column;gap:9px;min-width:0}

/* Failure to load the registry is not the same as an empty registry. */
.reg-grid .reg-fail{grid-column:1/-1}
.reg-grid .reg-fail .btn{margin-top:var(--sp-3)}

/* Register dialog: the reason a save was refused, in the dialog that refused it. */
.reg-note{color:var(--danger);font-size:var(--fs-tiny);min-height:16px}
.reg-hint{color:var(--text-faint);font-size:var(--fs-tiny);margin-top:4px}

/* ── phone: the vertical card wastes a screen on five names ── */
@media (max-width:560px){
  .reg-grid{grid-template-columns:1fr;gap:var(--sp-2)}
  .reg-grid .app-card{
    flex-direction:row;align-items:flex-start;gap:var(--sp-3);
    min-height:56px;padding:12px 13px;
  }
  .reg-grid .app-ico{margin-bottom:0;flex:0 0 auto;width:38px;height:38px}
  .reg-grid .a-body{min-width:0;flex:1;display:flex;flex-direction:column}
  .reg-grid .a-desc{margin-bottom:7px}
  .reg-grid .a-meta{margin-top:0}
  .reg-grid .a-flags{margin-top:7px}
  .reg-grid .reg-add{flex-direction:row;justify-content:flex-start;gap:10px}
  .reg-grid .reg-skel{min-height:0;flex-direction:row;align-items:center}
  .reg-grid .skel-col{flex:1;gap:8px}
}
@media (hover:none){
  /* 44px minimum touch target, and no hover lift to leave stuck on tap. */
  .reg-grid .app-card{min-height:56px}
  .reg-grid .app-card:hover{transform:none;box-shadow:none}
}

/* ══ embedded-tool host ══════════════════════════════════════════════════ */

/* One shade over the frame stack — only one frame is ever visible, so one
   overlay covers whichever it is. Its own background, because an iframe that
   never painted leaves whatever was behind it showing through. */
.af-shade{
  position:absolute;inset:0;z-index:2;background:var(--bg-base);
  display:flex;align-items:center;justify-content:center;padding:var(--sp-5);
}
.af-shade[hidden]{display:none}
.af-box{max-width:420px;width:100%;text-align:center}
.af-ico{display:flex;justify-content:center;font-size:34px;line-height:1;margin-bottom:var(--sp-3);color:var(--text-dim)}
.af-title{font-size:var(--fs-lead);font-weight:700;color:var(--text-bright)}
.af-msg{font-size:var(--fs-small);color:var(--text-dim);margin-top:6px;line-height:1.5}
.af-mono{
  font-family:var(--font-mono);font-size:var(--fs-tiny);color:var(--text-faint);
  background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;
  padding:3px 7px;display:inline-block;margin-top:10px;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom;
}
.af-acts{display:flex;gap:var(--sp-2);justify-content:center;margin-top:var(--sp-4);flex-wrap:wrap}

/* Indeterminate: we genuinely do not know how far a third-party tool has got. */
.af-bar{height:3px;width:150px;margin:var(--sp-4) auto 0;border-radius:3px;background:var(--bg-elevated);overflow:hidden}
.af-bar[hidden]{display:none}
.af-bar i{display:block;height:100%;width:38%;border-radius:3px;background:var(--accent);animation:af-slide 1.25s var(--ease) infinite}
@keyframes af-slide{0%{transform:translateX(-110%)}100%{transform:translateX(310%)}}
@media (prefers-reduced-motion:reduce){.af-bar i{animation:none;width:100%;opacity:.35}}
.af-shade[data-s="error"] .af-ico{color:var(--danger)}

/* The tool toolbar (tab strip + reload + open) is scoped so raising its touch targets doesn't
   reach the other views that share `.app-actions`. theme.css only bumps `.icon-btn` on touch,
   which left this bar at 23–30px tall — under the 44px floor, and now with one more control
   in it. */
@media (hover:none){
  .af-tools .btn{min-height:44px;min-width:44px;justify-content:center}
  .af-tools .seg{padding:3px}
  .af-tools .seg button{min-height:42px;display:inline-flex;align-items:center}
}

/* ── file picker (Station.pickFile) ── */
.pick-search{width:100%;margin-bottom:var(--sp-3)}
.pick-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:10px;max-height:52vh;overflow-y:auto;padding:2px}
.pick-item{
  font:inherit;text-align:left;cursor:pointer;color:var(--text);
  background:var(--bg-surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:9px;display:flex;flex-direction:column;gap:7px;min-width:0;
  transition:border-color var(--dur-fast),background var(--dur-fast);
}
.pick-item:hover{background:var(--bg-elevated);border-color:var(--border-light)}
.pick-thumb{
  height:74px;border-radius:6px;background:var(--bg-base) center/cover no-repeat;
  display:flex;align-items:center;justify-content:center;font-size:22px;color:var(--text-faint);
}
.pick-name{font-size:var(--fs-tiny);font-weight:600;color:var(--text-bright);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pick-sub{font-size:var(--fs-micro);color:var(--text-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pick-none{grid-column:1/-1}
@media (max-width:720px){
  /* ≥16px or iOS zooms the whole dialog on focus. */
  .pick-search{font-size:16px}
  .pick-grid{grid-template-columns:repeat(auto-fill,minmax(130px,1fr));max-height:46vh}
}
