/* ============================================================================
   base.css — reset, device frame, aurora field, screen skeleton, a11y
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; }

/* Author styles outrank the UA sheet's [hidden] rule, so any class that sets
   `display` would defeat el.hidden. Make hidden win everywhere, once. */
[hidden] { display: none !important; }

body {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--sp-6);
  background: var(--paper);
  color: var(--text);
  font: 400 var(--fs-body)/var(--lh-body) var(--font-ui);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; }
svg { display: block; }
img { max-width: 100%; display: block; }

/* ── Page-level aurora, bleeding behind and around the device ───────────── */
.page-aurora {
  position: fixed; inset: -10%;
  z-index: 0; pointer-events: none;
  background: linear-gradient(135deg,
    rgba(var(--sky-deep-rgb), .12) 0%,
    rgba(var(--violet-rgb),  .12) 100%);
}

/* ── Device frame ───────────────────────────────────────────────────────── */
.frame {
  position: relative; z-index: 1;
  width: var(--frame-w); height: var(--frame-h);
  display: flex; flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: 0 40px 90px -40px rgba(var(--ink-rgb), .45),
              0 0 0 10px rgba(var(--surface-rgb), .5);
  /* clip, not hidden: an overflow:hidden box is still a scroll container and
     can be scrolled programmatically — focus moving into an off-screen sheet
     scrolled the entire device. A clip container cannot scroll at all. */
  overflow: clip;
  isolation: isolate;
}

/* ── In-app ground — Deep Gradient, faded ────────────────────────────────
   The brand Deep Gradient (p.26, Deep Teal → Violet) run full-bleed across
   every screen and faded back over Soft White so it sits behind the content
   rather than competing with it.

   .22 is a legibility budget, not a taste call. Violet is the binding stop —
   it is far darker than Deep Teal — and ground text is --ink-soft:

       alpha   --ink-soft on the violet end
        .28      5.31:1   ← here
        .35      4.51:1   the ceiling, right on the AA line
        .40      4.00:1   fails

   One element, one background: no blend modes, no filter: blur(). The layer
   carries no filter, so the slow drift stays pure compositor work.          */
.aura {
  position: absolute; inset: -20%;
  z-index: 0; pointer-events: none;
  background:
    linear-gradient(135deg,
      rgba(var(--sky-deep-rgb), .28) 0%,
      rgba(var(--violet-rgb),  .28) 100%),
    var(--paper);
  animation: aura-drift 44s var(--ease-in-out) infinite alternate;
  will-change: transform;
}
@keyframes aura-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-3%, 2%, 0) scale(1.04); }
}

/* ── App bar ────────────────────────────────────────────────────────────── */
.appbar {
  position: relative; z-index: 30; flex: 0 0 auto;
  height: var(--appbar-h);
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 0 var(--sp-5);
  background: rgba(var(--surface-rgb), 0);
  border-bottom: 1px solid transparent;
  transition: background var(--t-hover) var(--ease-out),
              border-color var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out);
}
.appbar[data-scrolled="true"] {
  background: rgba(var(--surface-rgb), .86);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border-bottom-color: var(--line);
  box-shadow: var(--e-nav);
}
.appbar[hidden] { display: none; }
.appbar__title {
  font: 700 var(--fs-title)/1 var(--font-ui);
  letter-spacing: -.005em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.appbar__spacer { margin-left: auto; }

.wordmark {
  width: 83px; height: auto;
  flex: 0 0 auto;
}

/* ── Icon button ────────────────────────────────────────────────────────── */
.iconbtn {
  width: 48px; height: 48px; margin: 0 -6px;
  display: grid; place-items: center;
  border-radius: var(--r-pill); color: var(--ink);
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              transform var(--t-tap) var(--ease-out);
}
.iconbtn:active { transform: scale(.92); }
.iconbtn:focus-visible { outline: var(--focus-ring); outline-offset: -4px; }
@media (hover: hover) { .iconbtn:hover { background: var(--mist); } }

/* ── Screen stack ───────────────────────────────────────────────────────── */
.stack {
  position: relative; z-index: 10; flex: 1 1 auto;
  min-height: 0;
  display: grid;
}
.screen {
  grid-area: 1 / 1;
  display: grid; grid-template-columns: minmax(0, 1fr);
  grid-auto-rows: min-content;
  align-content: start; gap: var(--sp-4);
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  /* A classic desktop scrollbar inside a phone frame is both wrong-looking
     and the cause of a 13px horizontal overflow. Phones scroll without one. */
  scrollbar-width: none;
  padding: var(--sp-2) var(--sp-5) 0;
  scroll-padding-bottom: 96px;
}
.screen::-webkit-scrollbar { display: none; }
.screen[hidden] { display: none; }
.screen > :last-child { margin-bottom: 96px; }
.screen[data-nav="none"] > :last-child { margin-bottom: var(--sp-6); }
/* Chat clears the tab bar AND the composer pill floating above it. */
.screen[data-screen="chat"] > :last-child { margin-bottom: 168px; }

/* Screen transition (DESIGN.md §7.2) */
.screen[data-state="in"]      { animation: screen-in var(--t-screen) var(--ease-out) both; }
.screen[data-state="in"] > *  { animation: rise var(--t-reveal) var(--ease-out) both;
                                animation-delay: calc(var(--i, 0) * 40ms); }
@keyframes screen-in { from { opacity: 0; transform: scale(.985); } to { opacity: 1; transform: none; } }
@keyframes rise      { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* Scroll reveal (DESIGN.md §7.4).
   Scoped to .js so a script failure leaves the content visible rather than
   invisible — the observer is an enhancement, never the thing that renders. */
.reveal    { opacity: 1; }
.js .reveal{ opacity: 0; transform: translateY(10px); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity var(--t-reveal) var(--ease-out),
              transform var(--t-reveal) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 35ms);
}

/* ── Typographic primitives ─────────────────────────────────────────────── */
.eyebrow {
  font: 700 var(--fs-label)/var(--lh-label) var(--font-ui);
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft);
  transition: letter-spacing var(--t-reveal) var(--ease-out);
}
.reveal .eyebrow, .eyebrow.reveal { letter-spacing: .18em; }
.reveal.is-in .eyebrow, .eyebrow.reveal.is-in { letter-spacing: .1em; }

.display-l { font: 500 var(--fs-display-l)/var(--lh-display-l) var(--font-fig); letter-spacing: -.01em; }
.display-m { font: 500 var(--fs-display-m)/var(--lh-display-m) var(--font-fig); letter-spacing: -.01em; }
.title     { font: 700 var(--fs-title)/var(--lh-title) var(--font-ui); letter-spacing: -.005em; }
.body      { font: 400 var(--fs-body)/var(--lh-body) var(--font-ui); color: var(--text-2); }
.body-s    { font: 400 var(--fs-body-s)/var(--lh-body-s) var(--font-ui); color: var(--text-2); }
.meta      { font: 400 var(--fs-body-s)/var(--lh-body-s) var(--font-ui); color: var(--text-3); }

/* Text that sits on the app ground rather than on a surface must clear AA
   against the Light Gradient's darker stop. --text-2 measures 3.6:1 and
   --text-3 3.2:1 against Lavender: both were chosen when the page was
   near-white. --ink-soft clears it at 6.0:1, and 7.7:1 on the Mist end.
   Washing the gradient down instead would take it to ~25% strength before
   --text-3 passed, which is no longer the brand gradient. */
.screen .body, .screen .body-s, .screen .meta { color: var(--ink-soft); }
/* On a surface, the original scale stands — measured and unchanged. */
.card .body,  .card .body-s,  .sheet .body,  .sheet .body-s  { color: var(--text-2); }
.card .meta,  .sheet .meta                                   { color: var(--text-3); }
.strong    { font-weight: 600; color: var(--text); }

.fig, .fig-xl, .fig-l, .fig-m {
  font-family: var(--font-fig); font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.fig-xl { font-size: var(--fs-figure-xl); line-height: var(--lh-figure-xl); letter-spacing: -.02em; }
.fig-l  { font-size: var(--fs-figure-l);  line-height: var(--lh-figure-l);  letter-spacing: -.015em; }
.fig-m  { font-size: var(--fs-figure-m);  line-height: var(--lh-figure-m);  letter-spacing: -.01em; }

/* Figure XL mask reveal (DESIGN.md §7.3) */
.fig-xl.is-masked { clip-path: inset(0 0 100% 0); }
.fig-xl.is-revealed {
  clip-path: inset(0 0 0 0);
  transition: clip-path var(--t-figure) var(--ease-out);
}

/* ── Layout helpers ─────────────────────────────────────────────────────── */
/* Single-column grid helpers. The explicit minmax(0,1fr) matters: a default
   grid track floors at min-content, so one nowrap amount deep inside would
   push the whole screen past the frame at 320-360px. */
.stack-2, .stack-3, .stack-5, .stack-6 { display: grid; grid-template-columns: minmax(0, 1fr); }
.stack-2 { gap: var(--sp-2); }
.stack-3 { gap: var(--sp-3); }
.stack-5 { gap: var(--sp-5); }
.stack-6 { gap: var(--sp-6); }
.inline  { display: flex; align-items: center; gap: var(--sp-2); }
.inline-3{ display: flex; align-items: center; gap: var(--sp-3); }
.push    { margin-left: auto; }
.grow    { flex: 1 1 auto; min-width: 0; }
.truncate{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.divider { height: 1px; background: var(--line); border: 0; }

/* ── Accessibility ──────────────────────────────────────────────────────── */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }

/* ── Responsive (DESIGN.md §9) ──────────────────────────────────────────── */
@media (max-width: 639px) {
  :root { --frame-w: 100dvw; --frame-h: 100dvh; }
  body  { padding: 0; }
  .frame { border-radius: 0; border: 0; box-shadow: none; }
}

/* ── Reduced motion (DESIGN.md §7.8) ────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .aura { animation: none; }
  .screen[data-state="in"], .screen[data-state="in"] > * { animation: none; opacity: 1; transform: none; }
  .reveal { opacity: 1; transform: none; }
  .fig-xl.is-masked { clip-path: none; }
}
