/* danielsolves.ai — UI shared between index.html and portfolio.html.
   Navigation, project cards and their generated visuals, the voice-widget
   theming, accessibility helpers and the footer. Loads after styles/site.css
   and before each page's own <style>. */

/* ====================================================================
     danielsolves.ai — homepage
     Tokens and shared components come from styles/site.css. Everything
     below is homepage-specific and loads after it.
     ==================================================================== */

  /* Animatable angle for the rotating conic border on the featured plan. */
  @property --angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
  }

  :root {
    --ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  }

  /* --- Scroll progress ------------------------------------------------ */
  .scroll-progress {
    position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60;
    background: linear-gradient(90deg, var(--accent), var(--accent-3));
    transform: scaleX(0); transform-origin: 0 50%;
    pointer-events: none;
  }
  /* Native scroll-driven animation where supported: the compositor drives it,
     no scroll listener on the main thread. JS fallback handles the rest. */
  @supports (animation-timeline: scroll()) {
    .scroll-progress {
      animation: scrollProgress linear both;
      animation-timeline: scroll(root block);
    }
  }
  @keyframes scrollProgress { from { transform: scaleX(0); } to { transform: scaleX(1); } }

  /* --- Projects -------------------------------------------------------- */
  .p-body { gap: 0; }
  .p-links { margin-top: auto; padding-top: 28px; }
  .p-links .p-cta {
    background: none; padding: 0; cursor: pointer; font: inherit;
    display: inline-flex; align-items: center; gap: 9px;
    font-family: var(--mono); font-size: 13px; color: var(--text); text-decoration: none;
    border: none; border-bottom: 1px solid oklch(from var(--accent) l c h / 0.55); padding-bottom: 4px;
    transition: color 0.22s, gap 0.28s var(--ease-out-soft), border-color 0.22s;
  }
  .p-links .p-cta:hover { color: var(--accent); gap: 14px; border-bottom-color: var(--accent); }
  .p-links .p-soon {
    font-family: var(--mono); font-size: 12.5px; color: var(--faint);
    border: 1px solid var(--line); border-radius: var(--r-pill); padding: 6px 13px;
  }

  /* Designed default visual. An <image-slot> sits on top with its empty state
     hidden, so dropping a real screenshot simply covers the artwork. */
  .p-media { min-height: 300px; background: none; overflow: hidden; }
  .p-media image-slot::part(empty) { display: none !important; }
  .viz {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    background:
      radial-gradient(120% 100% at 50% 0%, oklch(from var(--accent) l c h / 0.10), transparent 62%),
      var(--bg-2);
    overflow: hidden;
  }
  .viz::before {
    content: ""; position: absolute; inset: 0; opacity: 0.5;
    background-image:
      linear-gradient(var(--grid-line) 1px, transparent 1px),
      linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
    background-size: 34px 34px;
    mask-image: radial-gradient(100% 80% at 50% 40%, #000 30%, transparent 78%);
  }
  .viz > * { position: relative; }


  /* Voice waveform */
  .viz-wave { display: flex; align-items: center; gap: 5px; height: 96px; }
  .viz-wave i {
    display: block; width: 4px; border-radius: 3px;
    background: linear-gradient(180deg, var(--accent), var(--accent-2));
    animation: waveBeat 1.25s ease-in-out infinite alternate;
    height: 16px;
  }
  @keyframes waveBeat { to { height: var(--h, 40px); } }

  /* App surface stack */
  .viz-stack { width: 100%; max-width: 300px; padding: 0 24px; display: flex; flex-direction: column; gap: 10px; }
  .viz-stack .card {
    border: 1px solid var(--line); border-radius: 11px; padding: 13px 15px;
    background: var(--surface-2);
    display: flex; align-items: center; gap: 11px;
  }
  .viz-stack .card .ring {
    width: 26px; height: 26px; border-radius: 50%; flex: none;
    background: conic-gradient(var(--accent) var(--p, 60%), var(--line-strong) 0);
    -webkit-mask: radial-gradient(circle, transparent 8px, #000 9px);
    mask: radial-gradient(circle, transparent 8px, #000 9px);
  }
  .viz-stack .card .bars { flex: 1; display: flex; flex-direction: column; gap: 6px; }
  .viz-stack .card .bars i { display: block; height: 5px; border-radius: 3px; background: var(--line-strong); }
  .viz-stack .card .bars i:last-child { width: 55%; }

  @media (prefers-reduced-motion: reduce) {
    .viz-mcp .pulse, .viz-mcp .pulse.is-active, .viz-mcp .pulse.is-back, .viz-wave i { animation: none; opacity: 0; }
    .viz-ngl .nglf-pulse, .viz-ngl .nglf-pulse.is-moving, .viz-ngl .nglf-pulse.is-failing,
    .viz-ngl .nglf-row.is-retrying .nglf-dot { animation: none; }
  }

  /* Fiona is the third project. Two image+text splits in a row is the cap, so
     this one runs full width instead of continuing the zigzag. */
  .project--band { display: block; padding: 0; }
  .band-viz { position: relative; height: 190px; display: flex; align-items: center; justify-content: center;
    background: radial-gradient(120% 140% at 50% 0%, oklch(from var(--accent) l c h / 0.12), transparent 62%),
      var(--bg-2);
    border-bottom: 1px solid var(--line); overflow: hidden; }
  .band-viz .viz-wave { height: 110px; gap: 7px; }
  .band-viz .viz-wave i { width: 5px; }
  .band-body { display: grid; grid-template-columns: 1fr auto; gap: 40px; align-items: center; padding: 34px 40px 38px; }
  .band-copy h3 { font-size: clamp(24px, 3vw, 32px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.08; }
  .band-copy p { color: var(--muted); font-size: var(--fs-card-copy); line-height: 1.6; margin-top: 14px; max-width: 62ch; text-wrap: pretty; }
  .band-copy .p-stack { margin-top: 20px; }
  .band-action { flex: none; }
  @media (max-width: 760px) {
    .band-body { grid-template-columns: 1fr; gap: 26px; padding: 28px 24px 32px; align-items: start; }
    .band-viz { height: 150px; }
  }

  /* --- Accessibility ------------------------------------------------------ */
  .skip-link {
    position: absolute; left: 12px; top: -100px; z-index: 100;
    background: var(--accent); color: var(--on-accent, var(--on-accent));
    font-family: var(--mono); font-size: 13px; font-weight: 600;
    padding: 12px 20px; border-radius: var(--r-control); text-decoration: none;
    transition: top 0.2s var(--ease-out-soft);
  }
  .skip-link:focus { top: 12px; }

  /* One visible focus ring for everything interactive, instead of an allowlist
     that quietly missed most links and buttons. */
  :where(a, button, input, textarea, select, [tabindex]):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: 4px;
  }

  /* Anchors would otherwise land under the sticky nav. */
  #main [id], .chat-form { scroll-margin-top: 88px; }

  /* Removes the ~300ms tap delay on iOS. */
  a, button, [role="button"], .chat-chip, .slot-card { touch-action: manipulation; }

  /* The DE/EN switch glyphs were a 15x16px target. Grow the hit area only. */
  .lang-btn { padding: 8px 6px; margin: -8px -6px; }

  .nav-panel { overscroll-behavior: contain; padding-bottom: max(48px, env(safe-area-inset-bottom)); }

  @media (prefers-reduced-motion: reduce) {
    html, .chat-messages { scroll-behavior: auto; }
    .nav-panel a { animation: none; }
  }

  :root[data-theme="light"] elevenlabs-convai,
  :root:not([data-theme="dark"]) elevenlabs-convai {
    --el-base: oklch(1 0 0);
    --el-base-hover: oklch(0.96 0.004 260);
    --el-base-active: oklch(0.93 0.006 260);
    --el-base-border: oklch(0.25 0.02 260 / 0.2);
    --el-base-subtle: oklch(0.44 0.015 260);
    --el-base-primary: oklch(0.22 0.015 260);
    --el-accent: oklch(0.58 0.13 195);
    --el-accent-hover: oklch(0.53 0.13 195);
    --el-accent-active: oklch(0.49 0.13 195);
    --el-accent-border: oklch(0.58 0.13 195 / 0.5);
    --el-accent-primary: oklch(0.99 0 0);
    --el-accent-subtle: oklch(0.58 0.13 195 / 0.12);
  }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) elevenlabs-convai { --el-base: oklch(0.15 0.012 260); }
  }

  /* --- Footer ----------------------------------------------------------- */
  footer { border-top: 1px solid var(--line); padding: 40px 0; margin-top: clamp(28px, 4vw, 45px); }
  .foot-inner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 18px; }
  .foot-inner .c { font-family: var(--mono); font-size: 12.5px; color: var(--faint); }
  /* Wraps: five links at 22px gaps overflowed a 320px viewport and made the whole
     page scroll sideways. */
  .foot-links { display: flex; flex-wrap: wrap; gap: 12px 22px; }
  .foot-links a { font-family: var(--mono); font-size: 12.5px; color: var(--muted); text-decoration: none; }
  .foot-links a:hover { color: var(--accent); }

/* Real mobile screens, composed without cropping the app's content. */
.sgr-preview { display: flex; align-items: center; justify-content: center; gap: 18px; padding: 32px 24px 62px; background: radial-gradient(ellipse at 50% 0, oklch(from var(--accent) l c h / .12), transparent 75%), var(--bg-2); }
.sgr-preview .iphone-frame { width: min(44%, 176px); flex: none; }
.sgr-preview .iphone-frame:nth-child(2) { transform: translateY(20px); }

.band-action .btn { flex: none; white-space: nowrap; }

/* A single attributed review supports the personal introduction. */
.client-feedback { margin: 40px 0 0; padding: clamp(22px, 3vw, 36px); border: 1px solid var(--line); border-radius: 18px; background: var(--surface); scroll-margin-top: 100px; }
.client-feedback-rating { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; }
.client-feedback-stars { color: var(--accent); font-size: 19px; letter-spacing: 3px; }
.client-feedback-score { font-size: 14px; font-weight: 600; }
.client-feedback-label { margin: 0 0 12px; color: var(--muted); font: 12px var(--mono); }
.client-feedback blockquote { margin: 18px 0 22px; }
.client-feedback blockquote p { margin: 0; max-width: 900px; font-size: clamp(20px, 2.2vw, 26px); line-height: 1.5; }
.client-feedback figcaption { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 14px 24px; color: var(--muted); font-size: 14px; }
.client-feedback-source { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
.client-feedback time { font-size: 12px; }
.client-feedback figcaption a { color: var(--text); text-underline-offset: 4px; }
.client-feedback figcaption a:hover { color: var(--accent); }
.client-feedback figcaption a:focus-visible { outline: 2px solid var(--accent); outline-offset: 5px; border-radius: 2px; }

/* Secondary hands-on demos follow the three full-size client references. */
.demo-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; margin-top: 22px; }
.demo-grid > .project { display: flex; flex-direction: column; min-width: 0; }
.demo-grid > .project .p-media { order: 0; height: 250px; min-height: 250px; flex: none; border-bottom: 1px solid var(--line); }

.demo-grid .p-body { padding: 28px; flex: 1; }
.demo-grid .p-links { margin-top: auto; flex-wrap: wrap; gap: 12px 18px; }
@media (max-width: 700px) {
  .demo-grid { grid-template-columns: minmax(0, 1fr); }
  .demo-grid .p-body { padding: 24px; }
}
