/* Live on-device demo panel, embedded in Project 02. Uses the site's design tokens
   (styles.css :root) so it inherits the dark/light theme automatically.
   Namespaced `lgd-` (leaf-grader-demo) to avoid the existing `ojo-` classes in Project 02. */

.lgd-demo { margin-top: var(--s-6); border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--bg-card); overflow: hidden; }

/* The site sets img/canvas { display:block } (an author rule), which overrides the browser's
   [hidden]{display:none}, so the HTML `hidden` attribute is ignored on this page. Force it back
   within the demo so hidden really hides the input/overlay/progress/result toggles. */
.lgd-demo [hidden] { display: none !important; }
.lgd-head { padding: var(--s-5) var(--s-5) 0; }
.lgd-tag { display: inline-flex; align-items: center; gap: var(--s-2); font-family: var(--font-mono);
  font-size: var(--fs-2xs); letter-spacing: .08em; text-transform: uppercase; color: var(--lime); }
.lgd-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--lime); animation: lgd-pulse 2s infinite; }
@keyframes lgd-pulse { 0% { box-shadow: 0 0 0 0 rgba(99,192,136,.5); } 70% { box-shadow: 0 0 0 8px rgba(99,192,136,0); }
  100% { box-shadow: 0 0 0 0 rgba(99,192,136,0); } }
.lgd-title { font-family: var(--font-serif); font-size: var(--fs-xl); margin: var(--s-2) 0; color: var(--text); }
.lgd-sub { font-size: var(--fs-sm); color: var(--text-mute); line-height: var(--lh-normal);
  max-width: 62ch; margin: 0 0 var(--s-4); }

/* ── "Interactive demo" signal ───────────────────────────────────────────────
   A labeled, lime-accented banner so visitors instantly recognize this as a hands-on
   demo of the thesis (not static content). The label carries the message on its own;
   the shimmer + dot pulse are CSS enhancements, and the down-arrow bob is JS-driven
   (ojo-demo.js) so it keeps moving under iOS Low Power Mode. */
.lgd-badge { position: relative; display: flex; align-items: center; gap: var(--s-2);
  margin-bottom: var(--s-3); padding: 7px var(--s-3);
  border: 1px solid var(--lime-deep);                                     /* fallback */
  border: 1px solid color-mix(in srgb, var(--lime) 45%, var(--line));
  border-radius: var(--r-md);
  background: rgba(99,192,136,.10);                                       /* fallback */
  background: color-mix(in srgb, var(--lime) 12%, transparent);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--lime); overflow: hidden; }
.lgd-badge-text { font-weight: 600; letter-spacing: .03em; }
.lgd-badge-arrow { margin-left: auto; padding-left: var(--s-2); font-size: var(--fs-base);
  line-height: 1; color: var(--lime); will-change: transform; }
.lgd-badge::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 32%, rgba(99,192,136,.20) 50%, transparent 68%);
  background-size: 220% 100%; background-repeat: no-repeat; background-position: 180% 0;
  animation: lgd-shimmer 3.4s ease-in-out infinite; }
@keyframes lgd-shimmer { 0% { background-position: 180% 0; } 100% { background-position: -90% 0; } }

/* Scroll-reveal: when the panel first enters the viewport it does a one-time rise + lime glow to
   draw the eye. Purely ADDITIVE: the panel is ALWAYS visible (never opacity:0), so it can never be
   left hidden if the observer or animation doesn't run (iOS Low Power Mode just skips the flourish). */
.lgd-demo.is-revealed { animation: lgd-reveal .9s var(--ease-out) 1; }
@keyframes lgd-reveal {
  0%   { transform: translateY(14px); box-shadow: 0 0 0 0 rgba(99,192,136,0); }
  45%  { box-shadow: 0 0 0 2px rgba(99,192,136,.5), 0 0 30px 2px var(--lime-glow); }
  100% { transform: translateY(0);   box-shadow: 0 0 0 0 rgba(99,192,136,0); }
}
@media (prefers-reduced-motion: reduce) {
  .lgd-demo.is-revealed { animation: none; }   /* respect reduced motion; the badge still signals it */
}

/* Two columns on desktop. minmax(0,...) on both tracks lets children shrink instead of
   forcing horizontal overflow. Breakpoints that collapse + tighten this live at the
   bottom of the file (Responsive block). */
.lgd-grid { display: grid; grid-template-columns: minmax(0,320px) minmax(0,1fr); gap: var(--s-5);
  padding: 0 var(--s-5) var(--s-5); max-width: 100%; }

.lgd-label { font-family: var(--font-mono); font-size: var(--fs-2xs); text-transform: uppercase;
  letter-spacing: .08em; color: var(--text-dim); margin: var(--s-4) 0 var(--s-2); }
.lgd-controls .lgd-label:first-child { margin-top: 0; }

.lgd-samples { display: grid; grid-template-columns: repeat(2,1fr); gap: var(--s-2); }
.lgd-sample { display: flex; flex-direction: column; align-items: center; padding: 0;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg-2); cursor: pointer;
  overflow: hidden; transition: border-color .15s var(--ease), box-shadow .15s var(--ease); }
.lgd-sample img { width: 100%; aspect-ratio: 1/1; object-fit: cover; display: block; }
.lgd-sample span { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-2);
  padding: var(--s-1) 0 var(--s-2); }
.lgd-sample:hover { border-color: var(--lime-deep); }
.lgd-sample.on { border-color: var(--lime); box-shadow: 0 0 0 1px var(--lime); }

.lgd-upload { display: block; text-align: center; padding: var(--s-3); border: 1px dashed var(--line-strong);
  border-radius: var(--r-md); background: var(--bg-1); color: var(--text-mute); font-size: var(--fs-sm);
  cursor: pointer; transition: border-color .15s, color .15s; }
.lgd-upload:hover { border-color: var(--lime-deep); color: var(--text-2); }

.lgd-models { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.lgd-model { flex: 1 1 140px; padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--bg-2); color: var(--text-2); font-size: var(--fs-sm); cursor: pointer; text-align: left;
  transition: border-color .15s, background .15s; }
.lgd-model em { display: block; font-style: normal; font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--text-dim); margin-top: 2px; }
.lgd-model.on { border-color: var(--lime); color: var(--text); background: var(--bg-3); }
.lgd-model.on em { color: var(--lime); }

.lgd-run { width: 100%; margin-top: var(--s-4); padding: var(--s-3); border: none; border-radius: var(--r-md);
  background: var(--lime); color: #04120a; font-weight: 600; font-size: var(--fs-md); font-family: var(--font-sans);
  cursor: pointer; transition: filter .15s, opacity .15s; }
.lgd-run:hover:not(:disabled) { filter: brightness(1.08); }
.lgd-run:disabled { opacity: .45; cursor: not-allowed; }
.lgd-note { font-size: var(--fs-xs); color: var(--text-mute); margin: var(--s-3) 0 0; min-height: 1.2em;
  line-height: 1.45; }
.lgd-note.err { color: var(--bad); }

.lgd-viewer { display: flex; flex-direction: column; }
/* Wide (2-column) layout: the stage grows to fill the viewer column so it matches the taller
   controls column instead of leaving empty space below it. The stacked layout below re-fixes a
   4:3 ratio since there is no tall sibling to match. */
.lgd-stage { position: relative; flex: 1 1 auto; min-height: 360px; border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.lgd-stage img, .lgd-stage canvas { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.lgd-placeholder { color: var(--text-dim); font-size: var(--fs-sm); padding: var(--s-4); text-align: center; }
/* Loading overlay: frosted, theme-aware scrim (color-mix off the live --bg token so it
   auto-adapts to light/dark) with a refined dual-ring spinner and an indeterminate
   lime sweep bar pinned to the bottom edge. Fades in gently each time it is shown. */
.lgd-progress { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: var(--s-3);
  background: rgba(7,8,10,.74);                                   /* fallback for no color-mix */
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  -webkit-backdrop-filter: blur(6px) saturate(1.15);
          backdrop-filter: blur(6px) saturate(1.15);
  color: var(--text-2); font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: .04em; text-align: center; padding: var(--s-5);
  animation: lgd-progress-in .35s var(--ease-out) both; }
#lgdProgressText { max-width: 26ch; line-height: var(--lh-normal); }

/* Dual-ring orbital spinner: outer lime arc + counter-rotating inner arc + soft halo. */
/* Rotation is driven from JS (requestAnimationFrame) in ojo-demo.js, NOT a CSS animation,
   so the spinner keeps moving even where CSS animations are paused (iOS Low Power Mode /
   Reduce Motion). The inner arc + halo below are static/decorative and rotate with it. */
.lgd-spinner { position: relative; width: 42px; height: 42px; border-radius: 50%; flex: none;
  border: 2px solid var(--line); border-top-color: var(--lime); border-right-color: var(--lime);
  will-change: transform; }
.lgd-spinner::before { content: ''; position: absolute; inset: 5px; border-radius: 50%;
  border: 2px solid transparent; border-bottom-color: var(--lime-deep); }
.lgd-spinner::after { content: ''; position: absolute; inset: -5px; border-radius: 50%;
  box-shadow: 0 0 14px 1px var(--lime-glow); animation: lgd-halo 1.8s ease-in-out infinite; }

/* Indeterminate progress sweep along the bottom edge of the stage. */
.lgd-progress::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background-color: var(--line);
  background-image: linear-gradient(90deg, transparent, var(--lime), transparent);
  background-repeat: no-repeat; background-size: 38% 100%; background-position: -40% 0;
  animation: lgd-bar 1.5s cubic-bezier(.65,0,.35,1) infinite; }

@keyframes lgd-spin { to { transform: rotate(360deg); } }
@keyframes lgd-progress-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes lgd-halo { 0%,100% { opacity: .55; } 50% { opacity: 1; } }
@keyframes lgd-bar { 0% { background-position: -40% 0; } 100% { background-position: 140% 0; } }

.lgd-toggle { display: flex; gap: var(--s-2); margin-top: var(--s-3); }
.lgd-toggle button { flex: 1; padding: var(--s-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--bg-2); color: var(--text-mute); font-size: var(--fs-xs); font-family: var(--font-mono);
  cursor: pointer; transition: border-color .15s, color .15s; }
.lgd-toggle button.on { border-color: var(--line-strong); color: var(--text); background: var(--bg-3); }

.lgd-result { margin-top: var(--s-4); display: flex; flex-wrap: wrap; gap: var(--s-5); align-items: center; }
.lgd-grade { display: flex; align-items: center; gap: var(--s-3); }
.lgd-grade-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 52px;
  height: 52px; padding: 0 var(--s-2); border-radius: var(--r-md); font-family: var(--font-mono); font-weight: 600;
  font-size: var(--fs-lg); color: #fff; background: var(--grade-c, var(--lime)); }
.lgd-grade-name { font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.lgd-grade-range { font-size: var(--fs-xs); color: var(--text-mute); font-family: var(--font-mono); }
.lgd-metrics { display: flex; gap: var(--s-6); flex-wrap: wrap; }
.lgd-metric-v { font-family: var(--font-mono); font-size: var(--fs-2xl); color: var(--text); line-height: 1; }
.lgd-metric-l { font-size: var(--fs-2xs); color: var(--text-mute); text-transform: uppercase;
  letter-spacing: .05em; margin-top: var(--s-1); }
.lgd-match { font-family: var(--font-mono); font-size: var(--fs-2xs); margin-top: var(--s-2);
  overflow-wrap: anywhere; }
.lgd-match.hit { color: var(--lime); }
.lgd-match.miss { color: var(--amber); }

/* ── Image bank: open button + modal gallery ─────────────────────────────────── */
.lgd-bank-open { width: 100%; margin-top: var(--s-2); padding: var(--s-3);
  border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--bg-2);
  color: var(--text-2); font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: 600;
  cursor: pointer; transition: border-color .15s, color .15s, background .15s; }
.lgd-bank-open:hover { border-color: var(--lime); color: var(--text); background: var(--bg-3); }

.lgd-bank-overlay { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center;
  justify-content: center; padding: var(--s-4);
  background: rgba(4,5,7,.72);                                      /* fallback */
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  animation: lgd-progress-in .2s var(--ease-out) both; }
/* The overlay lives at <body> level (moved out of .lgd-demo), so the panel's [hidden] fix does
   not reach it. Its own `display:flex` (author) would override the UA [hidden]{display:none} and
   leave it stuck visible+empty on load, so hide it explicitly when the hidden attribute is set. */
.lgd-bank-overlay[hidden] { display: none !important; }
.lgd-bank { display: flex; flex-direction: column; width: min(960px, 100%); max-height: 88vh;
  background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--r-lg);
  overflow: hidden; box-shadow: 0 24px 60px rgba(0,0,0,.5); }
.lgd-bank-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3);
  padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--line); }
.lgd-bank-title { font-family: var(--font-serif); font-size: var(--fs-lg); color: var(--text); margin: 0; }
.lgd-bank-sub { font-size: var(--fs-xs); color: var(--text-mute); margin: 2px 0 0; max-width: 52ch; }
.lgd-bank-close { flex: none; width: 34px; height: 34px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--bg-2); color: var(--text-2); font-size: var(--fs-lg);
  line-height: 1; cursor: pointer; transition: border-color .15s, color .15s; }
.lgd-bank-close:hover { border-color: var(--bad); color: var(--text); }

.lgd-bank-tabs { display: flex; flex-wrap: wrap; gap: var(--s-2); padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--line); }
.lgd-bank-tab { padding: 5px var(--s-3); border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--bg-2); color: var(--text-mute); font-family: var(--font-mono); font-size: var(--fs-2xs);
  letter-spacing: .03em; cursor: pointer; transition: border-color .15s, color .15s, background .15s; }
.lgd-bank-tab:hover { border-color: var(--lime-deep); color: var(--text-2); }
.lgd-bank-tab.on { border-color: var(--lime); color: var(--text); background: var(--bg-3); }

.lgd-bank-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: var(--s-2); padding: var(--s-4) var(--s-5); overflow-y: auto; }
.lgd-bank-item { position: relative; padding: 0; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--bg); cursor: pointer; overflow: hidden; aspect-ratio: 1/1;
  transition: border-color .12s; }
.lgd-bank-item:hover { border-color: var(--lime); }
.lgd-bank-item img { width: 100%; height: 100%; object-fit: contain; display: block; }
.lgd-bank-item .g { position: absolute; top: 4px; left: 4px; padding: 1px 5px; border-radius: var(--r-xs);
  font-family: var(--font-mono); font-size: 9px; font-weight: 700; color: #fff; letter-spacing: .02em; }
.lgd-bank-empty { grid-column: 1 / -1; color: var(--text-mute); font-size: var(--fs-sm);
  text-align: center; padding: var(--s-7); }
@media (max-width: 480px) {
  .lgd-bank-grid { grid-template-columns: repeat(auto-fill, minmax(74px, 1fr)); padding: var(--s-3); }
  .lgd-bank-head, .lgd-bank-tabs { padding-left: var(--s-4); padding-right: var(--s-4); }
}

/* ─── RESPONSIVE ───────────────────────────────────────────────────────────
   Fluid from ~320px phones to ultrawide. Every track uses minmax(0,...) or
   max-width:100% so nothing forces horizontal page scroll. Breakpoints:
   1024 (narrower control rail) : 720 (stack) : 480 (phone) : 360 (small phone). */

/* Keep everything inside the panel; images/canvas never exceed the stage. */
.lgd-demo, .lgd-stage { max-width: 100%; }
.lgd-stage img, .lgd-stage canvas { max-width: 100%; max-height: 100%; }
.lgd-sub, .lgd-note, .lgd-placeholder { overflow-wrap: anywhere; }

/* Tablet / small laptop: give the viewer more room, trim the control rail. */
@media (max-width: 1024px) {
  .lgd-grid { grid-template-columns: minmax(0,280px) minmax(0,1fr); gap: var(--s-4); }
}

/* Stack: controls sit above the viewer, both full width. */
@media (max-width: 720px) {
  .lgd-grid { grid-template-columns: 1fr; gap: var(--s-5); }
  .lgd-stage { flex: 0 0 auto; aspect-ratio: 4/3; min-height: 0; }   /* own ratio when not stretched */
}

/* Phones: tighter padding, wrapped metrics, ≥40px touch targets. */
@media (max-width: 480px) {
  .lgd-head { padding: var(--s-4) var(--s-4) 0; }
  .lgd-grid { padding: 0 var(--s-4) var(--s-4); }
  .lgd-title { font-size: var(--fs-lg); }
  .lgd-result { gap: var(--s-4); }
  .lgd-metrics { gap: var(--s-4); }
  .lgd-metric-v { font-size: var(--fs-xl); }
  .lgd-toggle button { min-height: 40px; }   /* comfortable tap target */
  .lgd-upload { padding: var(--s-4); }        /* keep upload label ≥40px tall */
}

/* Small phones (~320-360px): let model buttons wrap one-per-row, tighten sample gaps. */
@media (max-width: 360px) {
  .lgd-model { flex-basis: 100%; }
  .lgd-samples { gap: var(--s-1); }
  .lgd-grade-badge { min-width: 46px; height: 46px; }
}

/* ─── MOTION ───────────────────────────────────────────────────────────────
   Reduced-motion: drop the spinning and the sliding sweep bar (which can trigger
   vestibular discomfort), but keep a gentle opacity "breathe" so the loader still
   reads as working instead of a frozen, broken-looking ring. Opacity pulses are
   vestibular-safe. */
@media (prefers-reduced-motion: reduce) {
  /* The spinner ring keeps rotating (JS-driven) as an essential loading indicator.
     Only the decorative halo / sweep / status dot drop to a calm opacity pulse. */
  .lgd-spinner::after,
  .lgd-progress::after { animation: lgd-breathe 1.6s ease-in-out infinite; }
  .lgd-progress::after { background-position: 50% 0; }   /* no horizontal slide */
  .lgd-dot { animation: lgd-breathe 2s ease-in-out infinite; }
}
@keyframes lgd-breathe { 0%, 100% { opacity: .4; } 50% { opacity: 1; } }
