/* screens.css — screens, welcome, login, empty state, responsive
   Extracted verbatim from index.html lines 692-964 (the inline <style>).
   Design TOKENS are not here: they live in /assets/shell.css, shared with the
   document pages, exactly as before. */

/* ==========================================================================
   MOBILE — deliberately LAST in the file so it wins the cascade.
   The rail becomes an off-canvas drawer; tapping a companion closes it and
   reveals the conversation, which is what a phone user expects.
   ========================================================================== */

/* ===================== screens =====================
   welcome -> login -> app. Three full-viewport screens toggled by [hidden] rather
   than routed, because this is a clickthrough: the point is to SEE the chain, not
   to build navigation we would only throw away when the real app is wired. */
.screen[hidden]{display:none}

/* the boot frame: the ground colour and the mark, nothing else. Deliberately not a spinner —
   this resolves in well under a second and a spinner would flash more than it reassures. */
.boot{
  height:100dvh; display:grid; place-items:center; background:var(--bg);
}
.boot-mark{
  width:44px;height:44px;border-radius:var(--r2);
  background:linear-gradient(150deg,var(--accent-2),var(--accent-solid));
  display:grid;place-items:center;color:#fff;font-weight:600;font-size:var(--t-lg);
  box-shadow:0 0 0 1px rgba(255,255,255,.06), 0 6px 18px rgba(37,99,235,.28);
  animation:boot-pulse 1.4s var(--ease) infinite;
}
@keyframes boot-pulse{0%,100%{opacity:.55}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.boot-mark{animation:none;opacity:.8}}

/* ===================== welcome ===================== */
.welcome{
  height:100dvh; overflow-y:auto;
  display:flex; flex-direction:column; align-items:center;
  padding:var(--s8) var(--s5) var(--s6);
}
.welcome-inner{width:100%; max-width:940px; margin:auto}

.w-brand{display:flex; align-items:center; gap:var(--s3); justify-content:center; margin-bottom:var(--s7)}
.w-brand .brand-mark{
  width:34px;height:34px;border-radius:var(--r1);
  background:linear-gradient(140deg,var(--accent-2),var(--accent-solid));
  display:grid;place-items:center;font-weight:600;color:#fff;
}
.w-brand span{font-weight:600; letter-spacing:.01em}

.hero{text-align:center; max-width:620px; margin:0 auto}
/* Newsreader at display size on purpose: the landing is the first place the serif
   question can be judged as a headline rather than inside a chat bubble. */
.hero h1{
  font:400 var(--t-2xl)/1.15 var(--font-prose);
  font-size:clamp(30px, 6vw, 52px);
  margin:0 0 var(--s4); letter-spacing:-.01em; text-wrap:balance;
}
.hero h1 em{font-style:italic; color:var(--accent-2)}
.hero p{
  margin:0 auto var(--s6); max-width:52ch;
  color:var(--ink-2); font-size:var(--t-lg); line-height:1.6;
}
.hero-cta{display:flex; gap:var(--s3); justify-content:center; flex-wrap:wrap}

.btn-primary,.btn-ghost{
  padding:11px var(--s5); border-radius:var(--r-pill);
  font-size:var(--t-md); font-weight:500; transition:.18s var(--ease);
  /* One of these is an <a> now (Create an account), so the shared rule has to carry what a
     button gets for free: no underline, and a box that honours padding. */
  display:inline-block; text-decoration:none; text-align:center; cursor:pointer;
}
/* --accent-solid, not --accent: this carries white text (5.17:1 vs 3.68:1). */
.btn-primary{background:var(--accent-solid); color:var(--accent-ink); box-shadow:var(--shadow-1)}
.btn-primary:hover{background:var(--accent); transform:translateY(-1px)}
.btn-ghost{border:1px solid var(--line); color:var(--ink)}
.btn-ghost:hover{border-color:var(--accent-line); background:var(--bg-2)}

.w-cards{
  display:grid; grid-template-columns:repeat(3,1fr); gap:var(--s4);
  margin-top:var(--s8);
}
.w-card{
  background:var(--bg-2); border:1px solid var(--line-soft);
  border-radius:var(--r2); padding:var(--s5);
}
.w-card .ico{
  width:32px;height:32px;border-radius:var(--r1); margin-bottom:var(--s3);
  background:var(--accent-wash); display:grid; place-items:center;
}
.w-card .ico svg{width:17px;height:17px;stroke:var(--accent-2);fill:none;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.w-card h3{margin:0 0 var(--s2); font-size:var(--t-md); font-weight:600}
.w-card p{margin:0; color:var(--ink-2); font-size:var(--t-sm); line-height:1.6}

/* The disclosure is not decoration — Art.50(1) requires the AI nature to be stated up front.
   ⛔ It must NOT carry a blanket age claim. This said "18+" until [H] caught it 2026-08-16:
   Thalvix spreads across age bands, adult material is gated PER COMPANION (is_adult_only)
   against per-country thresholds, and under-16s can register with parental consent. A flat
   "18+" on the landing page contradicts the system the app actually implements. Any age line
   added here later has to come from those thresholds, not from a number written into markup. */
/* Deliberately QUIET. The load-bearing disclosure is the one shown at first contact with a
   companion (see the empty state, and v1 does the same) — this is a supplementary notice on
   a page where nobody is talking to anything yet, so it is sized to be read, not to shout. */
.w-legal{
  margin-top:var(--s6); padding:var(--s3) var(--s4);
  background:var(--notice-bg); border:1px solid var(--notice-line); border-radius:var(--r2);
  color:var(--notice-ink); font-size:var(--t-xs); line-height:1.55;
  display:flex; gap:var(--s3); align-items:flex-start;
  max-width:760px; margin-left:auto; margin-right:auto;
}
.w-legal svg{width:15px;height:15px;flex:none;margin-top:2px;stroke:currentColor;fill:none;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.w-legal b{color:#fbbf24}
.w-foot{margin-top:var(--s6); text-align:center; color:var(--ink-3); font-size:var(--t-xs)}

/* ===================== login ===================== */
.login-card{
  position:fixed; z-index:var(--z-sheet);
  top:50%; left:50%; transform:translate(-50%,-46%) scale(.98);
  width:min(400px, calc(100vw - 32px));
  background:var(--bg-1); border:1px solid var(--line);
  border-radius:var(--r3); padding:var(--s6) var(--s5) var(--s5);
  box-shadow:var(--shadow-2);
  opacity:0; pointer-events:none;
  transition:opacity .2s var(--ease), transform .28s var(--ease);
}
.login-card.open{opacity:1; pointer-events:auto; transform:translate(-50%,-50%) scale(1)}
.login-card h2{margin:0 0 var(--s1); font-size:var(--t-xl); font-weight:600}
.login-card .sub{margin:0 0 var(--s5); color:var(--ink-2); font-size:var(--t-sm)}
.field{margin-bottom:var(--s3)}
.field label{display:block; font-size:var(--t-xs); color:var(--ink-2); margin-bottom:6px}
.field input{
  width:100%; padding:10px var(--s3);
  background:var(--bg-3); border:1px solid var(--line); border-radius:var(--r1);
  /* Same iOS rule as the composer — the sign-in fields are text inputs too, and zooming the
     login card is if anything more disorienting than zooming the chat. */
  color:var(--ink); font:inherit; font-size:16px;
}
.field input:focus{outline:none; border-color:var(--accent-line); box-shadow:0 0 0 3px var(--accent-wash)}
.login-card .btn-primary{width:100%; margin-top:var(--s3)}
.login-note{
  margin-top:var(--s4); padding-top:var(--s4); border-top:1px solid var(--line-soft);
  color:var(--ink-3); font-size:var(--t-xs); text-align:center; line-height:1.6;
}

/* sign-in failure. Assertive enough to notice, not alarming - a typo is the common case. */
.login-error{
  margin:var(--s3) 0 0; padding:var(--s2) var(--s3);
  background:rgba(240,90,124,.10); border:1px solid rgba(240,90,124,.35);
  border-radius:var(--r1); color:var(--bad); font-size:var(--t-sm); line-height:1.5;
}
.login-error[hidden]{display:none}

/* "or" divider between the two sign-in routes */
.login-or{
  display:flex; align-items:center; gap:var(--s3);
  margin:var(--s4) 0 var(--s3); color:var(--ink-3); font-size:var(--t-xs);
}
.login-or::before,.login-or::after{content:''; flex:1; height:1px; background:var(--line)}
.login-or[hidden]{display:none}
.btn-passkey{
  width:100%; display:flex; align-items:center; justify-content:center; gap:var(--s2);
}
.btn-passkey[hidden]{display:none}
.btn-passkey svg{
  width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;
}

/* ===================== new-companion empty state ===================== */
/* Whether a chat with a NEW companion starts on the main page: it does. The thread
   area itself carries the introduction, so there is no separate screen and no modal,
   and the first message simply lands underneath it. */
/* ⚠ .thread-inner sets an explicit `display:flex`, which BEATS the UA stylesheet's
   [hidden]{display:none} — so the attribute alone does nothing here and both panes
   would render stacked. Same class of cascade bug as the mobile rail. */
.thread-inner[hidden]{display:none}
/* Kept dense on purpose: avatar + name + tagline + tags + the AI disclosure + three
   starters is a lot of vertical, and at a 900px-tall window the last starter fell
   behind the composer. Nothing here is optional, so the spacing gives instead. */
.empty-state{text-align:center; padding-top:var(--s2)}
.empty-state .avatar-xl{
  width:64px;height:64px;border-radius:50%;margin:0 auto var(--s3);
  display:grid;place-items:center;font-size:var(--t-lg);font-weight:600;color:#fff;
  box-shadow:var(--shadow-1);
}
.empty-state h2{margin:0 0 var(--s2); font-size:var(--t-xl); font-weight:600}
.empty-state .tagline{
  margin:0 auto var(--s4); max-width:46ch; color:var(--ink-2);
  font:400 var(--t-md)/1.6 var(--font-msg);
}
.es-meta{display:flex; gap:var(--s2); justify-content:center; flex-wrap:wrap; margin-bottom:var(--s4)}
.es-meta .tag{font-size:var(--t-xs)}
/* One compact line rather than the full bubble used mid-conversation. The Art.50(1)
   statement still has to be here and be legible — what gets cut is the padding and the
   second sentence, not the disclosure itself. */
/* ⚠ Do NOT put a `ch` max-width here. `ch` scales with font-size, so 52ch at --t-xs is
   NARROWER than the 560px inherited from .disclosure — it wrapped to an extra line and
   made the block TALLER than the full-size version it was meant to shrink. */
.disclosure.compact{
  align-self:center; text-align:left;
  padding:var(--s2) var(--s3); font-size:var(--t-xs); line-height:1.5;
  border-radius:var(--r1); margin-bottom:var(--s4);
}
.es-hint{color:var(--ink-3); font-size:var(--t-sm); margin:0 0 var(--s3)}
.starters{display:flex; flex-direction:column; gap:var(--s2); max-width:460px; margin:0 auto}
.starter{
  text-align:left; padding:10px var(--s4);
  background:var(--bg-2); border:1px solid var(--line-soft); border-radius:var(--r2);
  color:var(--ink); font-size:var(--t-sm); line-height:1.5;
  transition:.16s var(--ease);
}
.starter:hover{border-color:var(--accent-line); background:var(--bg-3); transform:translateY(-1px)}

/* a companion never spoken to has no preview line, so the row needs its own cue.
   This plus the "Not started yet" group header is the whole not-started signal —
   there is deliberately no NEW tag, because that slot belongs to RP/CW. */
.companion-last.unstarted{color:var(--ink-3); font-style:italic}


@media (max-width:860px){
  .app{grid-template-columns:1fr}

  .menu-btn{display:grid}

  /* ⭐ [H]'s placement: ABOVE the box on mobile, not beside it. flex-basis:100% forces its own
     line and order:-1 puts that line first, so the same three buttons move without a second copy
     in the markup. Left-aligned rather than stretched — they are 26px controls, not a toolbar. */
  .composer-inner{flex-wrap:wrap}
  .fmt-bar{flex-basis:100%;order:-1;align-self:flex-start;padding:0 0 var(--s1)}

  .rail{
    position:fixed; top:24px; left:0; bottom:0; width:min(320px,86vw);
    z-index:var(--z-sheet);
    transform:translateX(-100%);
    transition:transform .3s var(--ease);
    border-right:1px solid var(--line);
    box-shadow:var(--shadow-2);
  }
  .rail.open{transform:none}

  /* the chat owns the full viewport underneath */
  .chat{grid-column:1; min-height:0}

  /* roomier tap targets, and a touch more breathing space in the thread */
  .icon-btn{width:40px;height:40px}
  .thread{padding:var(--s5) var(--s3) var(--s6)}
  .thread-inner{gap:var(--s5)}
  .msg.ai .text{font-size:var(--t-md); line-height:1.6}
  .msg.me .text{max-width:88%}
  .composer{padding:var(--s2) var(--s3) calc(var(--s3) + env(safe-area-inset-bottom))}

  /* full-width sheet on a phone */
  .sheet{width:100%; border-radius:var(--r4) var(--r4) 0 0}
}

/* ---- new screens, mobile. A SECOND media block, deliberately after the first and
   still last in the file - same cascade reason as the comment near the top. */
@media (max-width:860px){
  .welcome{padding:var(--s7) var(--s4) var(--s6)}
  .w-cards{grid-template-columns:1fr; gap:var(--s3); margin-top:var(--s6)}
  .hero p{font-size:var(--t-md)}
  .hero-cta{flex-direction:column}
  .hero-cta button,.hero-cta a{width:100%}
  .empty-state{padding-top:var(--s5)}
}


/* ---- short viewports. The hero paragraph is the first thing to go when vertical space
   runs out: the headline and the two buttons are what the page is FOR, and on a landscape
   phone the paragraph alone pushes both off-screen. Height-based, not width-based - a
   portrait phone has plenty of room for it, a 390px-tall landscape one has none.
   ⛔ The AI notice is NEVER hidden at any size. Only this paragraph is optional. */
@media (max-height:640px){
  .hero p{display:none}
  .welcome{padding-top:var(--s5)}
  .w-brand{margin-bottom:var(--s5)}
  .w-cards{margin-top:var(--s5)}
}
