/* ============================================================
   Wonderkit web portal — prototype layout CSS
   Atoms come from the design system (wk-*); this adds the
   portal-specific shell, dashboard, billing & kid-space layout.
   ============================================================ */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body { background: var(--surface-canvas); font-family: var(--font-sans); color: var(--text-strong); }
#parent-app { min-height: 100vh; }
.pl-hidden { display: none !important; }

/* ── App shell ───────────────────────────────────────────────── */
.pl-app { display: flex; min-height: 100vh; }
.pl-sidebar {
  width: 248px; flex-shrink: 0; background: var(--white);
  border-right: 1px solid var(--border-hairline);
  display: flex; flex-direction: column; gap: 6px;
  padding: 18px 14px; position: sticky; top: 0; height: 100vh;
  transition: width var(--dur-base);
}
.pl-brand { display: flex; align-items: center; gap: 10px; padding: 6px 8px 14px; }
.pl-brand__logo { padding: 0; border: 0; background: transparent; display: flex; cursor: default; border-radius: 23%; }
.pl-brand__logo img { width: 34px; height: 34px; border-radius: 23%; box-shadow: 0 3px 8px rgba(124,58,237,.26); display: block; }
.pl-brand b { font-family: var(--font-display); font-weight: 600; font-size: 19px; color: var(--violet-800); letter-spacing: -0.02em; }
.pl-railtoggle { margin-left: auto; flex-shrink: 0; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--radius-sm); border: 0; background: transparent; color: var(--text-faint); cursor: pointer; transition: background var(--dur-base), color var(--dur-base); }
.pl-railtoggle:hover { background: var(--violet-50); color: var(--color-primary-ink); }

/* Collapsed (single-column) rail — desktop only. Gated to ≥861px so it can't
   fight the ≤860px horizontal-nav rules (which have lower specificity). */
@media (min-width: 861px) {
  .pl-sidebar.is-collapsed { width: 64px; min-width: 64px; max-width: 64px; overflow-x: hidden; padding: 18px 8px; }
  .pl-sidebar.is-collapsed .pl-brand { flex-direction: column; gap: 0; padding: 6px 0 14px; }
  .pl-sidebar.is-collapsed .pl-brand b { display: none; }
  .pl-sidebar.is-collapsed .pl-railtoggle { display: none; }
  .pl-sidebar.is-collapsed .pl-brand__logo { cursor: pointer; transition: transform var(--dur-fast); }
  .pl-sidebar.is-collapsed .pl-brand__logo:hover { transform: var(--lift-hover); }
  .pl-sidebar.is-collapsed .pl-navitem { justify-content: center; gap: 0; padding: 10px 0; }
  .pl-sidebar.is-collapsed .pl-navitem > span:not(.e) { display: none; }
  .pl-sidebar.is-collapsed .pl-navitem .e { width: 22px; }
  .pl-sidebar.is-collapsed .pl-navsep { margin: 12px 10px; }
  .pl-sidebar.is-collapsed .pl-planmini { display: none; }
}

/* ── Grown-up PIN gate (kid space) ───────────────────────────── */
.pl-pin { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(46, 16, 74, .45); backdrop-filter: blur(3px); }
.pl-pin__card { background: var(--white); border-radius: var(--radius-2xl); box-shadow: var(--shadow-lg); width: 100%; max-width: 340px; padding: 28px 24px 20px; text-align: center; }
.pl-pin__lock { font-size: 34px; line-height: 1; }
.pl-pin__card h2 { font-family: var(--font-display); font-weight: 600; font-size: 21px; margin: 8px 0 4px; color: var(--text-strong); }
.pl-pin__card p { font-size: 13.5px; color: var(--text-muted); line-height: 1.45; margin: 0 0 18px; }
.pl-pin__dots { display: flex; justify-content: center; gap: 14px; margin-bottom: 8px; }
.pl-pin__dots.is-error { animation: pl-pin-shake .45s; }
.pl-pin__dot { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--violet-200); background: transparent; transition: background var(--dur-fast), border-color var(--dur-fast); }
.pl-pin__dot.is-filled { background: var(--color-primary); border-color: var(--color-primary); }
.pl-pin__dots.is-error .pl-pin__dot { border-color: var(--color-danger); }
.pl-pin__err { min-height: 18px; font-size: 12.5px; font-weight: 600; color: var(--color-danger); margin-bottom: 14px; }
.pl-pin__pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.pl-pin__key { height: 58px; border-radius: var(--radius-lg); border: 1.5px solid var(--border-hairline); background: var(--white); font-family: var(--font-display); font-weight: 600; font-size: 22px; color: var(--text-strong); cursor: pointer; transition: background var(--dur-fast), transform var(--dur-fast); }
.pl-pin__key:hover { background: var(--violet-50); }
.pl-pin__key:active { transform: scale(.95); background: var(--violet-100); }
.pl-pin__key--util { font-size: 20px; color: var(--text-muted); border-style: dashed; }
.pl-pin__cancel { margin-top: 16px; border: 0; background: transparent; font: inherit; font-size: 13.5px; font-weight: 700; color: var(--color-primary-ink); cursor: pointer; }
.pl-pin__cancel:hover { text-decoration: underline; }
@keyframes pl-pin-shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-8px); } 40% { transform: translateX(7px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(3px); } }

/* Inline PIN setter (Account → Grown-up PIN) */
.pl-pinset { display: flex; flex-direction: column; align-items: center; border-top: 1px solid var(--border-hairline); margin: 4px 0 6px; padding: 18px 0 6px; }
.pl-pinset--bare { border-top: 0; margin: 0; padding: 4px 0 2px; }
.pl-pinset__label { font-size: 13.5px; font-weight: 700; color: var(--text-strong); margin-bottom: 14px; }
.pl-pinset__err { min-height: 18px; font-size: 12.5px; font-weight: 600; color: var(--color-danger); margin: 6px 0 2px; }
.pl-pinset__pad { width: 100%; max-width: 232px; }
.pl-pinset__actions { margin-top: 14px; }

.pl-nav { display: flex; flex-direction: column; gap: 2px; }
.pl-navitem {
  display: flex; align-items: center; gap: 11px; padding: 10px 12px;
  min-height: 42px; box-sizing: border-box;
  border-radius: var(--radius-md); border: 0; background: transparent;
  font: inherit; font-size: 14.5px; font-weight: 600; color: var(--text-muted);
  cursor: pointer; text-align: left; transition: background var(--dur-base), color var(--dur-base);
}
.pl-navitem .e { font-size: 18px; line-height: 1; width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.pl-navitem .e svg { display: block; }
.pl-navitem:hover { background: var(--violet-50); color: var(--color-primary-ink); }
.pl-navitem.is-active { background: var(--violet-100); color: var(--color-primary-ink); }
.pl-nav-spacer { flex: 1; }

/* Sidebar Kids section */
.pl-navsep { height: 1px; background: var(--border-hairline); margin: 12px 6px; }
.pl-kidsnav { display: flex; flex-direction: column; gap: 2px; }
.pl-kidsnav__label { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--text-faint); padding: 2px 12px 7px; }
/* kid profile: emoji inside a thin soft-violet ring (echoes the Me circle) */
.pl-navitem--kid .e { font-size: 14px; width: 21px; height: 21px; border: 1px solid var(--violet-200); border-radius: 50%; }
.pl-navitem--newkid { color: var(--color-primary-ink); font-weight: 700; }
.pl-navitem--newkid .e { font-size: 17px; color: var(--color-primary); }
.pl-navitem--newkid:hover { background: var(--violet-50); }

/* Plan mini-card in sidebar */
.pl-planmini { margin-top: 10px; padding: 13px; border-radius: var(--radius-lg); background: var(--violet-50); border: 1.5px solid var(--violet-150); }
.pl-planmini__row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 9px; }
.pl-planmini__name { font-weight: 800; font-size: 13px; color: var(--color-primary-ink); }
.pl-meter { height: 7px; border-radius: 999px; background: var(--violet-150); overflow: hidden; }
.pl-meter__fill { height: 100%; border-radius: 999px; background: var(--color-primary); }
.pl-meter--limit .pl-meter__fill { background: var(--amber-400); }
/* 3-segment credit bar (billing "This month"): used | plan-remaining | top-up */
.pl-creditbar { display: flex; height: 10px; border-radius: 999px; overflow: hidden; background: var(--ink-150); margin: 14px 0; }
.pl-creditbar__seg { height: 100%; }
.pl-creditbar__seg--used { background: var(--color-primary); }
.pl-creditbar__seg--plan { background: var(--ink-300); }
.pl-creditbar__seg--topup { background: var(--violet-150); }
.pl-creditbar.is-limit .pl-creditbar__seg--used { background: var(--amber-400); }
.pl-panel--limit { border-color: var(--amber-200); box-shadow: 0 0 0 3px var(--amber-100); }
.pl-preview-toggle { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 700; color: var(--text-faint); cursor: pointer; user-select: none; margin-right: 8px; }
.pl-preview-toggle input { accent-color: var(--color-primary); cursor: pointer; }
.pl-limit { display: flex; gap: 10px; align-items: flex-start; background: var(--amber-100); border: 1px solid var(--amber-200); border-radius: var(--radius-lg); padding: 12px 14px; }
.pl-limit__ic { font-size: 18px; line-height: 1.25; }
.pl-limit__t { flex: 1; font-size: 13px; color: var(--amber-900); line-height: 1.45; }
.pl-limit__t b { font-weight: 800; }

/* Credit top-ups */
.pl-topup__bal { font-size: 12.5px; font-weight: 800; color: var(--color-primary-ink); background: var(--color-primary-soft); padding: 4px 11px; border-radius: var(--radius-pill); }
.pl-topup__buy { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding: 6px 0 18px; border-bottom: 1px solid var(--border-hairline); }
.pl-topup__buyinfo { flex: 1; min-width: 180px; }
.pl-topup__price { font-family: var(--font-display); font-weight: 600; font-size: 20px; color: var(--text-strong); }
.pl-topup__price span { font-size: 14px; color: var(--text-muted); font-weight: 600; }
.pl-topup__sub { font-size: 12.5px; color: var(--text-muted); margin-top: 3px; }
.pl-stepper { display: inline-flex; align-items: center; border: 1.5px solid var(--border-strong); border-radius: var(--radius-pill); overflow: hidden; }
.pl-stepper button { width: 38px; height: 40px; border: 0; background: var(--white); font-size: 18px; cursor: pointer; color: var(--text-strong); transition: background var(--dur-base); }
.pl-stepper button:hover { background: var(--violet-50); }
.pl-stepper__v { min-width: 70px; text-align: center; font-weight: 700; font-size: 14.5px; font-variant-numeric: tabular-nums; }
.pl-stepper__v small { color: var(--text-muted); font-weight: 600; margin-left: 2px; }
.pl-topup__autorow { display: flex; align-items: center; gap: 14px; padding-top: 16px; }
.pl-topup__autocfg { margin-top: 14px; background: var(--surface-subtle); border: 1px solid var(--border-hairline); border-radius: var(--radius-lg); padding: 14px 16px; font-size: 14px; line-height: 2.2; color: var(--text-body); }
.pl-inlinesel { font: inherit; font-size: 13.5px; font-weight: 700; color: var(--color-primary-ink); background: var(--white); border: 1.5px solid var(--violet-200); border-radius: var(--radius-md); padding: 5px 9px; margin: 0 4px; cursor: pointer; }
.pl-inlinesel:focus { outline: none; border-color: var(--color-primary); }
.pl-topup__autonote { display: block; font-size: 12.5px; color: var(--text-muted); line-height: 1.5; margin-top: 8px; }
.pl-topbadge { display: flex; align-items: center; gap: 10px; background: var(--amber-100); border: 1px solid var(--amber-200); border-radius: var(--radius-md); padding: 8px 12px; font-size: 13px; }
.pl-topbadge span { flex: 1; font-weight: 700; color: var(--amber-900); }
.pl-topbadge b { font-weight: 800; color: var(--text-strong); font-variant-numeric: tabular-nums; }
.pl-limit__actions { display: flex; gap: 10px; margin-top: 12px; }
.pl-limit__actions > * { flex: 1; }
.pl-creditbreak { display: flex; gap: 18px; flex-wrap: wrap; font-size: 12.5px; font-weight: 700; color: var(--text-muted); margin-bottom: 6px; }
.pl-creditbreak span { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.pl-creditbreak i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }
.pl-limit--info { background: var(--violet-50); border-color: var(--violet-150); }
.pl-limit--info .pl-limit__t { color: var(--text-body); }

/* Out-of-credits notice inside chat */
.pl-climit { display: flex; gap: 12px; align-items: flex-start; background: var(--amber-100); border: 1px solid var(--amber-200); border-radius: var(--radius-lg); padding: 13px 16px; margin: 0 16px 12px; }
.pl-climit__ic { font-size: 18px; line-height: 1.3; flex-shrink: 0; }
.pl-climit__t { font-size: 13.5px; color: var(--amber-900); line-height: 1.5; }
.pl-climit__t b { font-weight: 800; }
.pl-climit__actions { display: flex; gap: 18px; margin-top: 9px; }
.pl-climit__link { font-size: 13.5px; font-weight: 800; color: var(--amber-800); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.pl-climit__link:hover { color: var(--amber-900); }

/* Lovable-style composer (auto-grow + voice) */
.pl-composer { border: 1.5px solid var(--border-strong); border-radius: var(--radius-xl); background: var(--white); padding: 8px 8px 8px; display: flex; flex-direction: column; gap: 4px; transition: border-color var(--dur-base), box-shadow var(--dur-base); }
.pl-composer:focus-within { border-color: var(--color-primary); box-shadow: 0 0 0 3px var(--color-primary-soft); }
.pl-composer__ta { border: 0; outline: 0; resize: none; font: inherit; font-size: 15px; line-height: 1.45; padding: 7px 8px 2px; background: transparent; color: var(--text-strong); max-height: 200px; min-height: 26px; overflow-y: auto; }
.pl-composer__ta::placeholder { color: var(--text-faint); }
.pl-composer__bar { display: flex; align-items: center; gap: 8px; }
.pl-composer__mic, .pl-composer__send { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; transition: background var(--dur-base), color var(--dur-base), filter var(--dur-base); }
.pl-composer__mic { width: 34px; height: 34px; border-radius: 50%; border: 0; background: var(--surface-subtle); color: var(--text-muted); }
.pl-composer__mic:hover { background: var(--violet-50); color: var(--color-primary-ink); }
.pl-composer__mic.is-rec { background: var(--color-danger); color: #fff; animation: pl-mic-pulse 1.2s ease-in-out infinite; }
@keyframes pl-mic-pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-danger) 50%, transparent); } 70% { box-shadow: 0 0 0 7px transparent; } }
.pl-composer__send { width: 36px; height: 36px; border-radius: 50%; border: 0; background: var(--color-primary); color: #fff; box-shadow: 0 4px 12px -4px var(--color-primary); }
.pl-composer__send:hover { filter: brightness(1.06); }
.pl-composer__send:disabled { opacity: .45; cursor: default; box-shadow: none; }

/* ── Chat attachments (spec 2026-07-18, handoff .att-*) ─────────────────────
   Pending-upload chips in the composer + the ＋ attach menu, and sent-bubble
   thumbnails. Design-system tokens (matches the handoff proto.css palette). */
.pl-composer__atts { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px 10px 0; }
/* The composer toggles these via the `hidden` attribute; an author-sheet
   display:flex would otherwise outrank the UA [hidden]{display:none} and leave
   the menu/strip permanently on-screen (the guardrail-#7 class-vs-[hidden] trap
   — a real click-trap: the abs-positioned menu would sit over the chips). */
.pl-composer__atts[hidden], .att-menu[hidden] { display: none; }
.att-chip { display: inline-flex; align-items: center; gap: 7px; max-width: 190px; padding: 5px 6px 5px 5px; background: var(--white); border: 1.5px solid var(--border-hairline); border-radius: var(--radius-md); font-size: 12.5px; color: var(--text-body); }
.att-chip img { width: 32px; height: 32px; border-radius: 6px; object-fit: cover; }
.att-chip--uploading { opacity: .6; }
.att-chip--error { border-color: var(--color-danger); }
.att-chip__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-chip__err { color: var(--color-danger); font-size: 11.5px; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-chip__x { flex-shrink: 0; width: 20px; height: 20px; border: 0; border-radius: 50%; background: var(--ink-100); color: var(--text-muted); font-size: 14px; line-height: 1; cursor: pointer; }
.pl-composer__addwrap { position: relative; display: inline-flex; }
.pl-composer__add { width: 32px; height: 32px; border: 0; border-radius: 50%; background: var(--surface-inset); color: var(--text-muted); font-size: 18px; line-height: 1; cursor: pointer; }
.pl-composer__add.is-open { background: var(--color-primary-soft); color: var(--color-primary); }
.att-menu { position: absolute; bottom: calc(100% + 8px); left: 0; z-index: 40; display: flex; flex-direction: column; min-width: 158px; padding: 6px; background: var(--white); border: 1px solid var(--border-hairline); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
.att-menu button { display: flex; align-items: center; gap: 11px; padding: 10px 12px; border: 0; background: transparent; border-radius: var(--radius-md); font: inherit; font-weight: 700; font-size: 14.5px; color: var(--text-strong); cursor: pointer; text-align: left; }
.att-menu button:hover { background: var(--surface-inset); }
.att-menu button span { display: inline-flex; color: var(--color-primary); }
.bub__atts { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 7px; }
.att-thumb img { width: 84px; height: 84px; border-radius: 10px; object-fit: cover; display: block; }

.pl-planmini__use { font-size: 11.5px; color: var(--text-muted); margin-top: 7px; }

/* ── Main column ─────────────────────────────────────────────── */
.pl-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pl-topbar {
  display: flex; align-items: center; gap: 14px; padding: 14px 28px;
  border-bottom: 1px solid var(--border-hairline); background: rgba(255,255,255,.7);
  backdrop-filter: blur(8px); position: sticky; top: 0; z-index: 5;
}
.pl-topbar__title { font-family: var(--font-display); font-weight: 600; font-size: 17px; color: var(--text-strong); }
.pl-topbar__sp { flex: 1; }
.pl-fam { display: inline-flex; align-items: center; gap: 9px; padding: 6px 8px 6px 12px; border-radius: var(--radius-pill); border: 1.5px solid var(--border-hairline); background: var(--white); cursor: pointer; font: inherit; }
.pl-fam:hover { border-color: var(--violet-200); }
.pl-fam__name { font-size: 13.5px; font-weight: 700; color: var(--text-body); }
.pl-content { padding: 34px 28px 56px; max-width: 1080px; width: 100%; }

/* Page header */
.pl-ph { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; margin-bottom: 22px; }
.pl-ph__t { flex: 1; min-width: 0; }
.pl-ph h1 { font-family: var(--font-display); font-weight: 600; font-size: 28px; letter-spacing: -0.02em; }
.pl-ph p { margin: 4px 0 0; color: var(--text-muted); font-size: 14.5px; }
.pl-ph__actions { display: flex; gap: 10px; }

/* ── Panels & cards ──────────────────────────────────────────── */
.pl-panel { background: var(--white); border: 1.5px solid var(--border-card); border-radius: var(--radius-xl); box-shadow: var(--shadow-sm); padding: 20px; }
.pl-panel__h { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.pl-panel__h h2 { font-family: var(--font-display); font-weight: 600; font-size: 18px; }
.pl-panel__h .sp { flex: 1; }
.pl-grid { display: grid; gap: 16px; }
.pl-grid--2 { grid-template-columns: 1fr 1fr; }
.pl-grid--3 { grid-template-columns: repeat(3, 1fr); }

/* Stat tiles */
.pl-stat { background: var(--white); border: 1.5px solid var(--border-card); border-radius: var(--radius-lg); padding: 16px 18px; }
.pl-stat__k { font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); display: flex; align-items: center; gap: 7px; }
.pl-stat__v { font-family: var(--font-display); font-weight: 600; font-size: 30px; margin-top: 8px; color: var(--text-strong); }
.pl-stat__v small { font-size: 15px; color: var(--text-faint); font-weight: 600; }
.pl-stat__sub { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }

/* Kid summary row card */
.pl-kidrow { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: var(--radius-lg); border: 1.5px solid var(--border-card); background: var(--white); cursor: pointer; transition: transform var(--dur-base), box-shadow var(--dur-base), border-color var(--dur-base); }
.pl-kidrow:hover { transform: var(--lift-hover); box-shadow: var(--shadow-hover); border-color: var(--violet-150); }
.pl-kidrow__info { flex: 1; min-width: 0; }
.pl-kidrow__name { font-family: var(--font-display); font-weight: 600; font-size: 15.5px; }
.pl-kidrow__meta { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.pl-kidrow__mini { display: flex; gap: 5px; }
.pl-kidrow__mini span { width: 26px; height: 26px; border-radius: 8px; background: var(--violet-50); border: 1px solid var(--violet-150); display: flex; align-items: center; justify-content: center; font-size: 14px; }

/* ── Kid detail header + tabs ────────────────────────────────── */
.pl-kidhead { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; }
.pl-kidhead__info { flex: 1; }
.pl-kidhead h1 { font-family: var(--font-display); font-weight: 600; font-size: 26px; }
.pl-kidhead__meta { color: var(--text-muted); font-size: 13.5px; margin-top: 2px; }
/* overflow-x:auto so the tab row scrolls instead of clipping the last tab on
   narrow phones; scrollbar hidden for a clean edge. */
.pl-tabs { display: flex; gap: 4px; border-bottom: 1.5px solid var(--border-hairline); margin-bottom: 20px; overflow-x: auto; scrollbar-width: none; }
.pl-tabs::-webkit-scrollbar { display: none; }
.pl-tab { padding: 10px 16px; border: 0; background: transparent; font: inherit; font-size: 14.5px; font-weight: 700; color: var(--text-muted); cursor: pointer; border-bottom: 2.5px solid transparent; margin-bottom: -1.5px; white-space: nowrap; }
.pl-tab:hover { color: var(--color-primary-ink); }
.pl-tab.is-active { color: var(--color-primary-ink); border-bottom-color: var(--color-primary); }

/* Clickable kid tile on the Kids page */
.pl-kidtile { transition: transform var(--dur-base), box-shadow var(--dur-base), border-color var(--dur-base); }
.pl-kidtile:hover { transform: var(--lift-card); box-shadow: var(--shadow-hover); border-color: var(--violet-150); }
.pl-kidtile > svg { color: var(--violet-400); flex-shrink: 0; }

/* Gallery (reuses wk-card / wk-creation) */
.pl-gallery { display: flex; flex-direction: column; gap: 12px; }

/* ── Agent settings ──────────────────────────────────────────── */
.pl-setrow { display: grid; grid-template-columns: 220px 1fr; gap: 24px; padding: 18px 0; border-bottom: 1px solid var(--border-hairline); align-items: start; }
.pl-setrow:last-child { border-bottom: 0; }
.pl-setrow__label { font-weight: 700; font-size: 14.5px; color: var(--text-strong); }
.pl-setrow__desc { font-size: 12.5px; color: var(--text-muted); margin-top: 3px; line-height: 1.4; }
.pl-setrow__control { min-width: 0; }

.pl-seg { display: inline-flex; background: var(--ink-100); border: 1.5px solid var(--border-hairline); border-radius: var(--radius-pill); padding: 3px; gap: 2px; flex-wrap: wrap; }
.pl-seg__opt { border: 0; background: transparent; font: inherit; font-size: 13px; font-weight: 700; color: var(--text-muted); padding: 7px 14px; border-radius: var(--radius-pill); cursor: pointer; white-space: nowrap; transition: background var(--dur-base), color var(--dur-base); }
.pl-seg__opt:hover { color: var(--color-primary-ink); }
.pl-seg__opt.is-active { background: var(--white); color: var(--color-primary-ink); box-shadow: var(--shadow-xs); }
/* On narrow screens a pill can't hold 4 options / long labels on one line — the
   default wrap leaves the selected pill floating in a lopsided rounded blob.
   Instead fill the control width and let options flex so each (possibly wrapped)
   row divides evenly, and soften the track to a rounded group, not a stretched
   pill. 3-option controls become an even single row; 4-option / long-label ones
   wrap into clean full-width rows. */
@media (max-width: 520px) {
  .pl-seg { display: flex; flex-wrap: wrap; width: 100%; border-radius: var(--radius-lg); }
  .pl-seg__opt { flex: 1 1 auto; text-align: center; border-radius: var(--radius-md); }
}

/* Agent preview bubble */
.pl-preview { background: var(--color-success-fill); border: 1.5px solid var(--color-success-border); border-radius: var(--radius-lg); padding: 14px 16px; }
.pl-preview__who { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--color-success); margin-bottom: 6px; }
.pl-preview__body { font-size: 14.5px; color: var(--ink-900); line-height: 1.5; }

/* ── Billing ─────────────────────────────────────────────────── */
.pl-plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.pl-plan { background: var(--white); border: 1.5px solid var(--border-card); border-radius: var(--radius-xl); padding: 18px; display: flex; flex-direction: column; gap: 12px; position: relative; }
.pl-plan.is-current { border-color: var(--color-primary); box-shadow: 0 0 0 3px var(--violet-100); }
.pl-plan__tag { position: absolute; top: -10px; left: 18px; }
.pl-plan__name { font-family: var(--font-display); font-weight: 600; font-size: 18px; }
.pl-plan__price { font-family: var(--font-display); font-weight: 600; font-size: 30px; color: var(--text-strong); }
.pl-plan__price small { font-size: 14px; color: var(--text-faint); font-weight: 600; }
.pl-plan__tagline { font-size: 12.5px; color: var(--text-muted); }
.pl-plan__feat { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.pl-plan__feat li { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; color: var(--text-body); }
.pl-plan__feat svg { color: var(--color-success); flex-shrink: 0; margin-top: 1px; }
.pl-plan__cta { margin-top: auto; }

.pl-pay { display: flex; align-items: center; gap: 14px; }
.pl-pay__chip { width: 52px; height: 34px; border-radius: 8px; background: linear-gradient(135deg, #8b5cf6, #6d28d9); display: flex; align-items: center; justify-content: center; color: #fff; }

/* ── Account ─────────────────────────────────────────────────── */
.pl-member { display: flex; align-items: center; gap: 13px; padding: 13px 0; border-bottom: 1px solid var(--border-hairline); }
.pl-member:last-child { border-bottom: 0; }
.pl-member__info { flex: 1; }
.pl-member__name { font-weight: 700; font-size: 14.5px; }
.pl-member__email { font-size: 12.5px; color: var(--text-muted); }

/* ── Danger zone ─────────────────────────────────────────────── */
.pl-danger { border: 1.5px solid var(--coral-200); background: #fffafa; border-radius: var(--radius-xl); padding: 6px 20px 14px; }
.pl-danger__head { display: flex; align-items: flex-start; gap: 12px; padding: 16px 0 12px; border-bottom: 1px solid var(--coral-100); }
.pl-danger__icon { font-size: 22px; line-height: 1.2; }
.pl-danger__head h2 { font-family: var(--font-display); font-weight: 600; font-size: 18px; color: var(--coral-700); }
.pl-danger__head p { margin: 2px 0 0; font-size: 13px; color: var(--text-muted); }
.pl-danger__row { display: flex; align-items: center; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--coral-100); }
.pl-danger__row:last-child { border-bottom: 0; }
.pl-danger__info { flex: 1; min-width: 0; }
.pl-danger__btn { flex-shrink: 0; white-space: nowrap; font: inherit; font-size: 13.5px; font-weight: 700; color: var(--coral-700); background: var(--white); border: 1.5px solid var(--coral-200); border-radius: var(--radius-pill); padding: 8px 16px; min-height: 38px; cursor: pointer; transition: background var(--dur-base), border-color var(--dur-base), color var(--dur-base); }
.pl-danger__btn:hover { background: var(--color-danger); border-color: var(--color-danger); color: #fff; }

/* Confirm modal warning banner */
.pl-confirm__warn { display: flex; gap: 10px; align-items: flex-start; background: var(--coral-100); border: 1px solid var(--coral-200); border-radius: var(--radius-md); padding: 12px 14px; font-size: 13.5px; line-height: 1.45; color: var(--coral-700); }

/* ── Modal ───────────────────────────────────────────────────── */
.pl-modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(31, 41, 55, .42); backdrop-filter: blur(4px); animation: pl-fade var(--dur-base) var(--ease-out); }
.pl-modal__card { background: var(--white); border-radius: var(--radius-2xl); box-shadow: var(--shadow-dialog); width: 100%; max-height: 90vh; overflow-y: auto; animation: pl-pop var(--dur-slow) var(--ease-out); }
.pl-modal__head { display: flex; align-items: center; gap: 12px; padding: 18px 20px 12px; }
.pl-modal__head h2 { flex: 1; font-family: var(--font-display); font-weight: 600; font-size: 19px; }
.pl-modal__body { padding: 4px 20px 8px; display: flex; flex-direction: column; gap: 16px; }
.pl-modal__foot { display: flex; justify-content: flex-end; gap: 10px; padding: 16px 20px 20px; }
@keyframes pl-fade { from { opacity: 0; } }
@keyframes pl-pop { from { opacity: 0; transform: translateY(8px) scale(.98); } }

/* Confirm-delete dialog — native <dialog> styled to match the lavender pill
   aesthetic. Built dynamically by portal/confirm-delete.js; loaded by BOTH
   parent.html (grown-up portal) and index.html (kid SPA). */
.cd-dialog {
  border: none; border-radius: 16px; padding: 20px 20px 16px;
  max-width: 340px; width: calc(100% - 32px);
  box-shadow: 0 10px 40px rgba(91,33,182,.18), 0 2px 8px rgba(0,0,0,.08);
  color: var(--ink-900);
}
.cd-dialog::backdrop { background: rgba(31,41,55,.32); backdrop-filter: blur(2px); }
.cd-dialog .cd-title { margin: 0 0 8px; font-size: 17px; font-weight: 600; }
.cd-dialog .cd-desc { margin: 0 0 18px; font-size: 14px; color: var(--ink-700); line-height: 1.45; }
.cd-dialog .cd-desc strong { color: var(--ink-900); font-weight: 600; }
.cd-dialog .cd-actions { display: flex; gap: 8px; justify-content: flex-end; }
.cd-dialog button {
  border: none; border-radius: 999px; padding: 10px 18px;
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  min-height: 40px; -webkit-tap-highlight-color: transparent;
  transition: background .12s ease;
}
.cd-dialog .cd-cancel { background: var(--violet-100); color: var(--violet-800); }
.cd-dialog .cd-cancel:hover { background: var(--violet-150); }
.cd-dialog .cd-delete { background: var(--coral-600); color: white; }
.cd-dialog .cd-delete:hover { background: var(--coral-700); }

/* Inline edit button beside a heading */
.pl-editname { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: var(--radius-pill); border: 0; background: transparent; color: var(--violet-400); cursor: pointer; flex-shrink: 0; transition: background var(--dur-base), color var(--dur-base); }
.pl-editname:hover { background: var(--violet-100); color: var(--color-primary-ink); }
.pl-kidhead h1 { display: inline-flex; align-items: center; gap: 4px; }

/* Inline-editable name input */
.pl-nameinput { font-family: var(--font-display); font-weight: 600; font-size: 26px; letter-spacing: -0.01em; color: var(--text-strong); border: 0; border-bottom: 2px solid var(--color-primary); background: var(--violet-50); border-radius: 6px 6px 0 0; padding: 2px 8px; outline: none; max-width: 340px; }
.pl-nameinput--sm { font-family: var(--font-sans); font-weight: 700; font-size: 14.5px; padding: 3px 7px; max-width: 240px; }

/* Inline-editable member name (owner's own name) */
.pl-member__name--editable { white-space: nowrap; }
.pl-editname--sm { display: inline-flex; vertical-align: middle; margin-left: 3px; width: 24px; height: 24px; opacity: .55; }
.pl-member__name--editable:hover .pl-editname--sm,
.pl-editname--sm:hover,
.pl-editname--sm:focus-visible { opacity: 1; }
.pl-editname--sm svg { width: 14px; height: 14px; }

/* Avatar with hover edit cue + emoji popover */
.pl-avedit { position: relative; cursor: pointer; border-radius: var(--radius-pill); flex-shrink: 0; }
.pl-avedit__cue { position: absolute; right: -2px; bottom: -2px; width: 24px; height: 24px; border-radius: 50%; background: var(--color-primary); color: #fff; display: flex; align-items: center; justify-content: center; border: 2px solid var(--white); opacity: 0; transform: scale(.8); transition: opacity var(--dur-base), transform var(--dur-base) var(--ease-out); }
.pl-avedit:hover .pl-avedit__cue { opacity: 1; transform: scale(1); }
.pl-avedit:hover .wk-avatar { filter: brightness(.97); }
/* 7 columns / 2 rows for the 14-emoji set: 7×36 cells + 6×4 gaps + 2×8 padding = 292px. */
.pl-avpop { position: absolute; top: calc(100% + 8px); left: 0; z-index: 20; display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; background: var(--white); border: 1.5px solid var(--border-card); border-radius: var(--radius-lg); box-shadow: var(--shadow-dialog); padding: 8px; width: 292px; }
.pl-avpop__opt { width: 36px; height: 36px; border-radius: var(--radius-md); border: 1.5px solid transparent; background: transparent; font-size: 22px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background var(--dur-base), border-color var(--dur-base); }
.pl-avpop__opt:hover { background: var(--violet-50); }
.pl-avpop__opt.is-sel { background: var(--violet-100); border-color: var(--color-primary); }

/* ── Auth (signup / onboarding) ──────────────────────────────── */
.pl-auth { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--gradient-hero); }
.pl-authcard { background: var(--white); border-radius: var(--radius-3xl); box-shadow: var(--shadow-lg); width: 100%; max-width: 440px; padding: 34px 32px; }
.pl-authcard--wide { max-width: 440px; }
.pl-auth__brand { display: inline-flex; align-items: center; gap: 11px; margin-bottom: 18px; }
.pl-auth__brand img { width: 38px; height: 38px; border-radius: 23%; box-shadow: 0 3px 8px rgba(124,58,237,.26); }
.pl-auth__brand b { font-family: var(--font-display); font-weight: 600; font-size: 22px; color: var(--violet-800); }
.pl-auth h1 { font-family: var(--font-display); font-weight: 600; font-size: 26px; letter-spacing: -0.01em; }
.pl-auth p.sub { color: var(--text-muted); margin: 6px 0 22px; font-size: 14.5px; }
.pl-auth__fields { display: flex; flex-direction: column; gap: 14px; }
.pl-auth__divider { display: flex; align-items: center; gap: 12px; color: var(--text-faint); font-size: 12px; margin: 18px 0; }
.pl-auth__divider::before, .pl-auth__divider::after { content: ""; flex: 1; height: 1px; background: var(--border-hairline); }
.pl-steps { display: flex; gap: 6px; margin-bottom: 20px; }
.pl-step { height: 5px; flex: 1; border-radius: 999px; background: var(--violet-150); }
.pl-step.is-done { background: var(--color-primary); }
.pl-social { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.pl-social__btn { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; padding: 13px 16px; border: 1.5px solid var(--border-strong); border-radius: var(--radius-pill); background: var(--white); font: inherit; font-size: 15px; font-weight: 700; color: var(--text-strong); cursor: pointer; transition: border-color var(--dur-base), background var(--dur-base), transform var(--dur-fast); }
.pl-social__btn { white-space: nowrap; }
.pl-social__btn:hover { border-color: var(--color-primary); background: var(--violet-50); transform: var(--lift-hover); }
.pl-social__g, .pl-social__a { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; font-family: var(--font-display); font-weight: 700; font-size: 14px; }
.pl-social__g { background: var(--violet-100); color: var(--color-primary-ink); }
.pl-social__a { background: var(--text-strong); color: var(--white); font-size: 13px; }
/* Cap the row so the 14-emoji set wraps 7+7: 7×52 cells + 6×10 gaps = 424px. */
.pl-avpick { display: flex; gap: 10px; flex-wrap: wrap; max-width: 424px; }
.pl-avpick button { width: 52px; height: 52px; border-radius: var(--radius-lg); border: 2px solid var(--border-hairline); background: var(--violet-50); font-size: 26px; cursor: pointer; transition: border-color var(--dur-base), transform var(--dur-fast); }
.pl-avpick button:hover { transform: var(--lift-hover); }
.pl-avpick button.is-sel { border-color: var(--color-primary); background: var(--violet-100); }

/* "Prefer not to say" opt-out under the onboarding Age field. */
.pl-ob-agena { display: flex; align-items: center; gap: 6px; margin-top: 2px; font-size: 12.5px; font-weight: 500; color: var(--text-muted); cursor: pointer; }
.pl-ob-agena input { width: auto; margin: 0; cursor: pointer; }

/* Sign-up redesign 2026-07-12 — layout per HANDOFF-signup.md. Onboarding card
   widens to 500px ≥ tablet (the add-kid subtitle stays on one line); the
   avatar picker becomes a balanced 5-col grid; name(1fr)+age(88px) share a
   row with the age checkbox right-aligned below. */
@media (min-width: 768px) {
  .pl-authcard--wide { max-width: 500px; }
  .pl-avpick { display: grid; grid-template-columns: repeat(5, 1fr); }
  .pl-avpick button { width: auto; }
}
.pl-grid--kidage { display: grid; grid-template-columns: 1fr 88px; gap: 12px; }
.pl-ob-agena { justify-content: flex-end; }
.pl-ob-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
.pl-ob-actions .wk-btn--primary { flex: 1; min-width: 0; }

/* Step-0 wrong-account escape ("Signed in as … — not you? Sign out"). Quiet,
   muted line under Continue; mirrors the landing's .lp-auth__switch treatment
   (landing.css isn't loaded on /parent, so the pattern lives here too). */
.pl-ob-identity { margin: 2px 0 0; text-align: center; font-size: 13px; color: var(--text-muted); }
.pl-ob-identity button { border: 0; background: transparent; font: inherit; font-weight: 800; color: var(--color-primary-ink); cursor: pointer; padding: 0; }
.pl-ob-identity button:hover { text-decoration: underline; }

/* Add-kid view (#/newkid): Cancel left, primary Add kid right. */
.pl-newkid__actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 2px; }

/* ── Grown-up chat — two columns, each with its OWN header so the chat
   header (back + title + space button) and the preview header (Live preview +
   Tablet/Phone) sit side by side at the top. The chat column is the wider
   share (was 440 → +80%); the preview pane flexes to fill the rest. ──────── */
.pl-content:has(.pl-gchat) { padding: 0; max-width: none; }
.pl-gchat { display: flex; flex-direction: column; height: 100dvh; }
.pl-gchat__title { display: inline-flex; align-items: center; gap: 9px; min-width: 0; font-family: var(--font-display); font-weight: 600; font-size: 19px; color: var(--text-strong); }
.pl-gchat__title .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-gchat__split { flex: 1; display: flex; min-height: 0; overflow: hidden; }
/* flex-basis 792px but ALLOWED to shrink (0 1) so in the 861–~1100px band — where
   the fixed 792 would squeeze the preview pane to a sliver before the 860px stack
   kicks in — the chat column gives ground gracefully. At desktop widths there's
   slack, so it holds 792. */
.pl-gchat__col { flex: 0 1 792px; min-width: 0; display: flex; flex-direction: column; min-height: 0; background: var(--white); position: relative; }
/* Per-column chat header — height-matched to the preview bar (same vertical
   padding + bottom border) so the two column tops align. */
.pl-gchat__chathead { box-sizing: border-box; display: flex; align-items: center; gap: 12px; min-height: 57px; padding: 8px 16px; border-bottom: 1px solid var(--border-hairline); background: var(--white); flex: 0 0 auto; }
/* basis 360 (not 0) so in the narrow band the preview keeps a usable width and
   the shrinkable chat column (flex 0 1 792) yields to it instead of being pinned
   at 792; at desktop widths there's slack so the pane still grows to fill. */
.pl-gchat__split > .pl-preview-pane { flex: 1 1 360px; min-width: 0; border-left: 1px solid var(--border-hairline); }
/* Structural chat-column slots, shared by BOTH surfaces via class (parent:
   #tx-messages/#tx-climit-slot/#tx-composer; kid: #chat-log/#kid-climit-slot/
   #kid-composer). Class-targeted (not id-scoped) so the grown-up and kid chats
   render from the exact same rules. The transcript box scrolls; the climit +
   composer stay pinned, or a long conversation pushes the composer off-screen. */
.pl-gchat__col .pl-gchat__log { flex: 1 1 0; min-height: 0; overflow-y: auto; padding: 16px 18px; position: relative; display: flex; flex-direction: column; gap: 10px; }
.pl-gchat__col .pl-gchat__climit, .pl-gchat__col .pl-gchat__composer { flex: 0 0 auto; }
/* Full-width composer (CV1): the mounted .pl-composer fills the column; keep
   it a plain block (a stray row-flex would shrink it to its content). The 16px
   side margins are the desired gutter. */
.pl-gchat__col .pl-gchat__composer { display: block; margin: 8px 16px 14px; padding: 0; position: relative; }
/* Lovable-style fade (CV2): a gradient veil just above the composer so chat
   history dissolves into the surface instead of ending at a hard edge. Anchored
   to the composer's top and stretched past the 16px gutters to the column edges. */
.pl-gchat__col .pl-gchat__composer::before {
  content: ""; position: absolute; left: -16px; right: -16px; bottom: 100%; height: 36px;
  background: linear-gradient(to top, var(--white), transparent); pointer-events: none;
}

/* ── Shared chat primitives (skeleton shimmer, soft pill, suggestion chips,
   user bubble) — used by BOTH the grown-up chat (parent.js) and the kid chat
   (kid.js). These were duplicated, with subtle drift, in app.css and the
   index.html inline <style>; consolidated here (one tokenized copy) so the two
   surfaces can't diverge. Surface-specific LAYOUT variants (the #tx-messages
   chat skeleton, the kid .skel-chat/.skel-circle shapes, .suggestion-row
   padding, .suggestion-row--composer) stay with their surface. ─────────────── */
.skel {
  background: linear-gradient(110deg, var(--violet-150) 30%, var(--violet-50) 50%, var(--violet-150) 70%);
  background-size: 220% 100%;
  animation: skel-shimmer 1.6s ease-in-out infinite;
}
@keyframes skel-shimmer {
  0%   { background-position: 220% 0; }
  100% { background-position: -120% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skel { animation: skel-pulse 1.8s ease-in-out infinite; background: var(--violet-150); background-size: auto; }
  @keyframes skel-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .6; } }
}

/* Agent-settings tab (kid-detail 5b): the controls paint instantly but stay
   inert + dimmed until the GET resolves (PR #84 gate) — no value reads as a
   saved config and no click can persist before real settings arrive. A soft
   pulse signals the load; reduced-motion drops it (the dim + inert stay). */
.pl-panel.is-loading { pointer-events: none; opacity: .6; animation: pl-loading-pulse 1.8s ease-in-out infinite; }
@keyframes pl-loading-pulse { 0%, 100% { opacity: .6; } 50% { opacity: .42; } }
@media (prefers-reduced-motion: reduce) { .pl-panel.is-loading { animation: none; } }

/* ── Portal load skeletons (rail rows + home cards/rows) ──────────────────────
   Shown while /family/creations is in flight. Dimensions mirror the real markup
   (.pl-navitem, .pl-stat, .wk-creation, 48px disc) so the swap-in doesn't
   reflow. The .skel shimmer + reduced-motion fallback are defined just above. */
.pl-skel-line, .pl-skel-bar { border-radius: 6px; display: block; }
.pl-skel-dot, .pl-skel-disc, .pl-skel-pill { display: block; flex: none; }
.pl-skel-railrow { cursor: default; }
.pl-skel-railrow:hover { background: transparent; }
.pl-skel-dot { width: 22px; height: 22px; border-radius: 50%; }
.pl-skel-bar { height: 12px; }
.pl-skel-disc { width: 48px; height: 48px; border-radius: var(--radius-lg); }
.pl-skel-pill { width: 88px; height: 32px; border-radius: var(--radius-pill); margin-left: auto; }
.pl-skel-creation { pointer-events: none; }

/* One-time fade-in as real content (rail + home) replaces the skeleton. */
.pl-fade-in { animation: pl-fade-up var(--dur-slow) var(--ease-out) both; }
@keyframes pl-fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .pl-fade-in { animation: none; }
}

.pill-soft {
  background: var(--violet-100); border: 1.5px solid var(--violet-200); color: var(--violet-800); border-radius: var(--radius-pill);
  transition: background .15s ease, transform .12s ease, box-shadow .15s ease;
}
.pill-soft:hover { background: var(--violet-150); transform: translateY(-1px); }
.pill-soft:active { transform: translateY(0); }
@keyframes chip-in { from { opacity: 0; transform: translateY(2px); } }
.suggestion-chip {
  min-height: 40px; display: inline-flex; align-items: center; gap: 6px; padding: 0 14px;
  font-family: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.suggestion-chip:disabled { opacity: .5; cursor: wait; transform: none; }
.suggestion-chip .sc-emoji { font-size: 14px; line-height: 1; }
.user-bubble { align-self: flex-end; background: var(--violet-150); border-radius: var(--radius-lg); padding: 10px 14px; max-width: 80%; font-size: 15px; color: var(--text-strong); }
.user-bubble.grownup-bubble { align-self: flex-end; }
/* Assistant bubble (grown-up copilot): mobile ChatBubble parity — a simple
   left-aligned, capped bubble with no role label and no internal separator,
   scoped so power.html's full-width transcript card is untouched. */
.pl-gchat .pu-thread { align-self: flex-start; max-width: 84%; border-radius: var(--radius-lg); padding: 11px 14px; }
.pl-gchat .pu-answer { border-top: 0; margin-top: 0; padding-top: 0; }

/* ── Kid space (mobile-first, on the sunny gradient) ─────────── */
.pl-kidspace { min-height: 100vh; background: var(--gradient-hero); display: flex; flex-direction: column; }
.pl-ks-inner { width: 100%; max-width: 760px; margin: 0 auto; flex: 1; display: flex; flex-direction: column; min-height: 0; }
.pl-ks-gallery { flex: 1; overflow-y: auto; padding: 8px 16px 20px; display: flex; flex-direction: column; gap: 12px; }
/* Kid-space nav moved to the floating bottom pill (#kid-bottomnav, index.html);
   the old top strip (.pl-ks-nav / .pl-ks-tab) + header (.pl-ks-head) + hold-to-
   exit button (.pl-ks-grown) were removed with the round-4 shell. */

/* Parent portal — kid Gallery tab */
.pl-kg-bar { display: flex; align-items: center; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.pl-kg-bar__hint { flex: 1; min-width: 220px; font-size: 13.5px; color: var(--text-muted); line-height: 1.45; }
.wk-btn.is-disabled { opacity: .5; cursor: not-allowed; }
/* ── Shared creation tile + grid — SINGLE SOURCE OF TRUTH ───────────────────
   Used by all three surfaces: /me Saved/Likes (me.js), the grown-up kid-detail
   Gallery, and the kid SPA gallery (index.html, which links portal.css + feed.css
   — feed.css only for the feed tab; the tile rules all live here). auto-fill+minmax
   enforces the SAME ~210-250px tile width in every container (narrow portal content
   w/ sidebar, the wide adult area, the 760px kid SPA) so they all flex column COUNT
   instead of shrinking the tile — the fix for "/me shows small tiles, kid SPA shows
   big ones". Values copied verbatim from the former .me-* (me.css). Kept
   self-contained (shimmer + reduced-motion below) so the tiles never depend on
   feed.css load order. */
.creation-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; }
.creation-tile { border: 1px solid var(--border-card); border-radius: var(--radius-lg); overflow: hidden; background: var(--white); box-shadow: var(--shadow-xs); padding: 0; transition: transform var(--dur-fast), box-shadow var(--dur-base); }
.creation-tile:hover { transform: var(--lift-hover); box-shadow: var(--shadow-sm); }
/* The media holds the webp thumbnail (creation-thumb.js) over a dark stage.
   It's also the only region that opens the creation (the body below is
   metadata + controls), so the pointer lives here. The card still lifts on
   hover — the lift is the card's affordance, the cursor is the target's. */
.creation-tile__media { position: relative; aspect-ratio: 4 / 5; background: #0c0a14; overflow: hidden; cursor: pointer; }
/* Shimmer covers the thumbnail pending state (.creation-tile__media.is-pending,
   from creation-thumb.js + me.js's skeleton cell) until the webp resolves or
   falls back. Reuses the lp-shimmer keyframe defined later in this file. */
.creation-tile__media.is-pending::before { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(100deg, #15111f 30%, #261c39 50%, #15111f 70%) 0 0 / 200% 100%; animation: lp-shimmer 1.3s linear infinite; }
/* Thumbnail media (creation-thumb.js): the webp contains over the dark stage;
   the no-thumb fallback is the kid tint (inline) + centered kind emoji + a small
   kind badge — mirrors the mobile SocialTile fallback. */
.creation-tile__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
.creation-tile__fallback { position: absolute; inset: 0; display: grid; place-items: center; }
.creation-tile__femoji { font-size: 44px; line-height: 1; }
.creation-tile__fkind { position: absolute; left: 7px; bottom: 7px; padding: 3px 8px; border-radius: var(--radius-pill); background: var(--white); color: var(--text-strong); font-size: 10px; font-weight: 800; }
@media (prefers-reduced-motion: reduce) {
  .creation-tile__media.is-pending::before { animation: none; }
}
/* Body mirrors the former .me-tile__body: the name (2-line clamp), the "by <kid>"
   line, then (galleries only) the per-tile share slot. title="" surfaces the full
   name on hover. */
.creation-tile__body { padding: 10px 11px 12px; }
.creation-tile__name { font-size: 13.5px; font-weight: 800; color: var(--text-strong); line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Cross-family grids only (/me Saved+Liked): the creator name is a link to that
   kid's public gallery. Reset the anchor to the muted metadata look; the tile
   body is otherwise inert, so this is the only click target below the media. */
.creation-tile__by { display: inline-block; font-size: 12px; color: var(--text-faint); margin-top: 3px; text-decoration: none; }
.creation-tile__by:hover { color: var(--color-primary); text-decoration: underline; }

/* ── Gallery-only hooks: the kid-detail + kid SPA galleries render the shared
   .creation-tile PLUS .pl-kg-tile (tile = <div class="pl-kg-tile creation-tile">).
   .pl-kg-tile carries position:relative (the badge/hidetag anchor) + the edit-mode
   behavior; .creation-tile owns the shared visual. Drafts dash the border + dim the
   media; the per-tile Share button / read-only dots sit under the by-line — the one
   surface-specific difference (grown-up = Share button, kid SPA = .cs-dots). ── */
.pl-kg-tile { position: relative; }
.pl-kg-tile.is-draft { border-style: dashed; border-color: var(--violet-200); }
.pl-kg-tile.is-draft .creation-tile__media { background: #1a1330; }
/* Footer row under the name: the display-only like/bookmark counts sit on the
   LEFT; the adult gallery's icon-only Share control is pushed RIGHT by
   .pl-kg-tile__sharewrap. The row owns the top gap, so the inner share slot/dots
   no longer add their own margin-top. (counts carries no margin-left:auto — the
   share wrap owns the push, so the kid SPA's counts-only foot lays out left.) */
.creation-tile__foot { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.pl-kg-tile__sharewrap { display: inline-flex; margin-left: auto; }
.creation-tile__counts { display: inline-flex; gap: 8px; align-items: center; font-size: 12px; font-weight: 700; color: var(--text-muted); }
.creation-tile__counts span { display: inline-flex; align-items: center; gap: 3px; }
.creation-tile__counts svg { width: 14px; height: 14px; }

/* Gallery edit mode — wiggle, delete badge, drag-reorder (kid + parent) */
.pl-ks-gridbar { display: flex; justify-content: flex-end; padding: 0 16px 8px; }
.pl-ks-editbtn { padding: 8px 16px; border: 1.5px solid var(--violet-200); background: rgba(255,255,255,.7); border-radius: var(--radius-pill); font: inherit; font-size: 13px; font-weight: 700; color: var(--color-primary-ink); cursor: pointer; white-space: nowrap; transition: background var(--dur-base), border-color var(--dur-base); }
.pl-ks-editbtn:hover { background: var(--violet-50); border-color: var(--violet-300); }
.pl-ks-editbtn.is-on { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }
.pl-tile-badge { position: absolute; top: -9px; left: -9px; z-index: 4; width: 26px; height: 26px; border-radius: 50%; background: var(--text-strong); color: #fff; border: 2px solid var(--white); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: var(--shadow-sm); padding: 0; }
.pl-tile-badge.is-unhide { background: var(--color-primary); }
.pl-tile-badge:hover { filter: brightness(1.12); }
.pl-kg-tile.is-dragging { opacity: .4; }
.pl-kg-tile.is-editing { cursor: grab; }
.pl-kg-tile.is-editing:active { cursor: grabbing; }
/* cursor is INHERITED, not cascaded by ancestor specificity — the two rules
   above only reach .creation-tile__media because it used to set no cursor of
   its own. Now that the media has its own `cursor: pointer` (see the
   .creation-tile__media rule above), that wins on the media unless overridden
   here explicitly, showing a click-to-open pointer over what is actually a
   drag surface in edit mode. */
.pl-kg-tile.is-editing .creation-tile__media { cursor: grab; }
.pl-kg-tile.is-editing:active .creation-tile__media { cursor: grabbing; }
@media (prefers-reduced-motion: no-preference) {
  .pl-kg-tile.is-editing { animation: tile-wiggle .24s ease-in-out infinite alternate; }
  .pl-kg-tile.is-editing:nth-child(2n) { animation-name: tile-wiggle-b; animation-duration: .27s; }
}
@keyframes tile-wiggle { from { transform: rotate(-1.3deg); } to { transform: rotate(1.3deg); } }
@keyframes tile-wiggle-b { from { transform: rotate(1.4deg); } to { transform: rotate(-1.2deg); } }

/* Hidden-when-shared group: separator, dimmed tiles, drop zone */
.pl-kg-sep { display: flex; align-items: center; gap: 12px; margin: 20px 0 14px; }
.pl-kg-sep::before, .pl-kg-sep::after { content: ""; flex: 1; height: 1.5px; background: var(--border-hairline); }
.pl-kg-sep__l { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--text-faint); white-space: nowrap; }
.creation-grid--hidden { border: 1.5px dashed var(--border-hairline); border-radius: var(--radius-xl); padding: 14px; min-height: 168px; }
.pl-kg-tile.is-hidden { opacity: .42; }
.pl-kg-drop { grid-column: 1 / -1; display: flex; align-items: center; justify-content: center; text-align: center; color: var(--text-faint); font-size: 13px; font-weight: 600; padding: 18px; }
/* Pure label, absolutely positioned OVER the artwork as a SIBLING of the
   media — pointer-events: none so it never swallows clicks in its footprint;
   they fall through to the tile underneath. */
.pl-kg-tile__hidetag { position: absolute; top: 10px; right: 10px; display: inline-flex; align-items: center; gap: 4px; font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); background: var(--surface-subtle); border: 1px solid var(--border-hairline); padding: 3px 7px; border-radius: var(--radius-pill); pointer-events: none; }
.pl-confirm__warn--info { background: var(--violet-50); border-color: var(--violet-150); color: var(--text-body); }

/* Gallery tile grid */
.pl-ks-scroll { flex: 1; overflow-y: auto; padding: 16px 16px 24px; }
/* .pl-ks-grid is retained only for the loading skeleton (SKEL_KS_GRID). The kid
   gallery now renders the shared .creation-grid / .creation-tile (identical to the
   parent gallery + /me), so the old .pl-ks-tile* visual rules were removed. */
.pl-ks-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; align-content: start; }
.pl-ks-newcard { display: flex; align-items: center; gap: 14px; border: 2.5px dashed var(--violet-400); background: rgba(255,255,255,.6); border-radius: var(--radius-xl); padding: 16px 18px; cursor: pointer; }
.pl-ks-newcard .ic { font-size: 26px; }
.pl-ks-newcard .nm { font-family: var(--font-display); font-weight: 600; font-size: 16px; color: var(--color-primary); }
.pl-ks-newcard .sub { font-size: 12px; color: var(--text-muted); }

.pl-ks-inner--wide { max-width: 1180px; }
/* Kid chat goes edge-to-edge: beat the .pl-ks-inner 760px base (double-class
   for specificity) so the kid's grown-up-style split fills the viewport. */
.pl-ks-inner.pl-ks-inner--wide { max-width: none; }

/* Preview pane shell */
.pl-preview-pane { display: flex; flex-direction: column; min-height: 0; background: var(--surface-canvas); }
.pl-preview-bar { display: flex; align-items: center; gap: 9px; padding: 11px 14px; border-bottom: 1px solid var(--border-hairline); background: var(--white); }
.pl-preview-bar__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--color-success); box-shadow: 0 0 0 3px var(--color-success-fill); flex-shrink: 0; }
.pl-preview-bar__t { font-size: 13px; font-weight: 700; color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-preview-seg { display: inline-flex; background: var(--ink-100); border-radius: var(--radius-pill); padding: 3px; gap: 2px; flex-shrink: 0; }
.pl-preview-seg button { border: 0; background: transparent; font: inherit; font-size: 12px; font-weight: 700; color: var(--text-muted); padding: 5px 12px; border-radius: var(--radius-pill); cursor: pointer; }
.pl-preview-seg button.is-on { background: var(--white); color: var(--color-primary-ink); box-shadow: var(--shadow-xs); }
/* size container so the device can fit-to-height via cqh; centered, minimal pad. */
.pl-preview-stage { flex: 1; min-height: 0; overflow: hidden; display: flex; align-items: center; justify-content: center; padding: 12px; container-type: size; background: repeating-linear-gradient(45deg, var(--surface-subtle), var(--surface-subtle) 12px, var(--surface-canvas) 12px, var(--surface-canvas) 24px); }

/* Device frames — the device ALWAYS fits the stage in BOTH axes: width is the
   min of a max px, the stage height (cqh, via aspect-ratio), AND the stage
   width (cqw, so a narrow preview pane never clips it sideways). aspect-ratio
   drives height; the screen fills it. */
.pl-device { box-sizing: border-box; background: #211c33; border-radius: 30px; padding: 14px; box-shadow: 0 22px 50px -18px rgba(31,16,58,.55), inset 0 0 0 1.5px rgba(255,255,255,.06); flex-shrink: 0; }
.pl-device--tablet { aspect-ratio: 3 / 4; width: min(540px, 74cqh, 94cqw); }
.pl-device--phone { aspect-ratio: 9 / 19; width: min(300px, 46cqh, 94cqw); border-radius: 38px; padding: 11px; }
.pl-device__screen { width: 100%; height: 100%; background: #fff; border-radius: 16px; overflow: hidden; container-type: inline-size; }
.pl-device--phone .pl-device__screen { border-radius: 28px; }
.pl-preview-iframe { width: 100%; height: 100%; border: 0; display: block; background: #fff; }
/* Live build preview reveal (mirrors the feed's [data-live] / creation-player
   dark→fade): while the opaque-origin iframe loads, a dark backdrop fills the
   screen; the iframe fades in on its `load` event (.is-loaded). No loading
   text/spinner. `.is-build` scopes this to a real build so the empty/error
   states keep their light gradient. */
.pl-device__screen.is-build { position: relative; background: #15111f; }
.pl-device__screen.is-build::before { content: ""; position: absolute; inset: 0; background: linear-gradient(120deg, #15111f 28%, #261c39 50%, #15111f 72%); background-size: 200% 100%; animation: lp-shimmer 1.3s linear infinite; }
.pl-device__screen.is-build .pl-preview-iframe { position: relative; z-index: 1; opacity: 0; transition: opacity .45s ease; }
.pl-device__screen.is-build.is-loaded .pl-preview-iframe { opacity: 1; }
.pl-device__screen.is-build.is-loaded::before { opacity: 0; animation: none; transition: opacity .3s ease; }
/* lp-shimmer also lives in feed.css, but keep a copy here so this file is
   self-contained — the kid chat preview shimmer animates regardless of whether
   feed.css is present or loads first. */
@keyframes lp-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .pl-device__screen.is-build .pl-preview-iframe { transition: none; } .pl-device__screen.is-build::before { animation: none; } }

/* ── Fullscreen interactive player ───────────────────────────────
   MOVED here from feed.css (PR #100 follow-up): the kid page's "View" opens this
   same in-page overlay player (openPlayer), so the player lives here to keep
   portal.css self-contained. The grown-up portal loads both feed.css + portal.css.
   Reuses the lp-shimmer keyframe defined just above. */
.fw-player { position: fixed; inset: 0; z-index: 1000; background: rgba(10, 6, 20, .92); backdrop-filter: blur(10px); display: flex; align-items: center; justify-content: center; padding: 0; animation: fw-fade .22s ease; transition: opacity .2s ease, backdrop-filter .2s ease; }
@keyframes fw-fade { from { opacity: 0; } }
/* animated close: fade the overlay + ease the stage down (see openPlayer) */
.fw-player.is-closing { opacity: 0; backdrop-filter: blur(0); }
.fw-player.is-closing .fw-player__stage { transform: scale(.96); }

/* stage fills the viewport edge-to-edge. Cards/stories have a defined portrait
   aspect ratio, so they scale to the largest size that fits (contain) and
   letterbox on the long axis. Games have no fixed ratio, so they fill the whole
   overlay via 100% (not 100vw, which includes the scrollbar gutter and made wide
   games overflow). The entrance zoom transforms the stage (laid out once at final
   size) with transform+opacity only — compositor-thread, no per-frame layout, and
   the iframe never reflows (will-change is set on the element for the duration). */
.fw-player__stage { position: relative; flex-shrink: 0; transition: transform .22s ease; }
.fw-player__stage.is-tall { aspect-ratio: 420 / 900; height: min(100dvh, 100vw * 900 / 420); width: auto; max-width: 100vw; max-height: 100dvh; }
.fw-player__stage.is-wide { width: 100%; height: 100%; }
/* dark→fade reveal (mirrors the feed's [data-live] / live-preview.js): while the
   sandboxed creation loads, a dark shimmer fills the stage; the frame starts
   transparent and fades in on its `load` event (.is-loaded) — no loading
   label, no black flash. The frame sits ABOVE the ::before backdrop (z-index +
   pointer-events:none on the shimmer) so the interactive creation is never
   click-blocked once revealed. */
.fw-player__frame { width: 100%; height: 100%; border: 0; border-radius: 0; background: #000; display: block; position: relative; z-index: 1; opacity: 0; transition: opacity .45s ease; }
.fw-player__stage.is-loaded .fw-player__frame { opacity: 1; }
.fw-player__stage::before { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(100deg, #17101f 30%, #221634 50%, #17101f 70%) 0 0 / 200% 100%; animation: lp-shimmer 1.3s linear infinite; }
.fw-player__stage.is-loaded::before, .fw-player__stage.is-error::before { animation: none; opacity: 0; transition: opacity .3s ease; }
/* fetch-failure state: centered retry over the dark stage (exit affordances stay live).
   This box has display:grid + inset:0/z-index:3 over the interactive frame, so when
   inactive it MUST not render — that's guaranteed globally by the `[hidden]{display:
   none!important}` reset in app.css (don't reintroduce a per-element [hidden] rule). */
.fw-player__error { position: absolute; inset: 0; z-index: 3; display: grid; place-content: center; gap: 12px; padding: 24px; text-align: center; color: #fff; font-size: 15px; }
.fw-player__retry { border: 0; border-radius: 999px; padding: 9px 18px; background: rgba(255, 255, 255, .14); color: #fff; cursor: pointer; font: inherit; }
.fw-player__retry:hover { background: rgba(255, 255, 255, .24); }

/* chrome — only a close button, anchored to the viewport corner (always on
   screen, over any creation content); Esc also closes. */
.fw-player__x { position: absolute; top: 16px; right: 16px; z-index: 6; width: 42px; height: 42px; border-radius: 50%; border: 0; background: rgba(18, 12, 28, .55); color: #fff; cursor: pointer; display: grid; place-items: center; font-size: 19px; backdrop-filter: blur(4px); transition: background var(--dur-base), transform var(--dur-fast); }
.fw-player__x:hover { background: rgba(18, 12, 28, .82); transform: rotate(90deg); }

/* Honor reduced-motion fully: the JS already skips the entrance zoom + close
   ease, so here drop the remaining backdrop fade-in, close transitions, and the
   ✕ hover spin. */
@media (prefers-reduced-motion: reduce) {
  .fw-player { animation: none; transition: none; }
  .fw-player__stage { transition: none; }
  .fw-player__stage::before { animation: none; }
  .fw-player__frame { transition: none; }
  .fw-player__x { transition: background var(--dur-base); }
  .fw-player__x:hover { transform: none; }
}

/* Preview content (themed mocks) */
.pv { width: 100%; height: 100%; overflow: auto; font-family: var(--font-sans); --pv: var(--color-primary); }
.pv--empty { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; padding: 30px; color: var(--text-muted); background: linear-gradient(160deg, var(--violet-50), #fff); }
.pv-empty__ic { font-size: 44px; }
.pv-empty__t { font-family: var(--font-display); font-weight: 600; font-size: 17px; color: var(--text-strong); }
.pv-empty__s { font-size: 13px; max-width: 220px; line-height: 1.5; }
.pv-btn { border: 0; background: var(--pv); color: #fff; font: inherit; font-weight: 800; font-size: clamp(13px, 4cqw, 16px); padding: 12px 22px; border-radius: 999px; cursor: pointer; box-shadow: 0 6px 16px -6px var(--pv); }

.pv-card { display: flex; align-items: center; justify-content: center; padding: 7cqw; background: radial-gradient(120% 120% at 50% 0%, color-mix(in srgb, var(--pv) 16%, #fff), #fff); }
.pv-card__inner { width: 100%; background: #fff; border: 2px solid color-mix(in srgb, var(--pv) 30%, #fff); border-radius: 20px; padding: 9cqw 6cqw; text-align: center; box-shadow: 0 10px 30px -14px rgba(0,0,0,.2); }
.pv-card__emoji { font-size: clamp(48px, 22cqw, 110px); line-height: 1; }
.pv-card__title { font-family: var(--font-display); font-weight: 600; font-size: clamp(20px, 7cqw, 34px); color: var(--pv); margin: 4cqw 0 2cqw; letter-spacing: -.01em; }
.pv-card__msg { font-size: clamp(13px, 4.2cqw, 18px); color: var(--text-body); }
.pv-card__deco { display: flex; justify-content: center; gap: 10px; font-size: clamp(18px, 6cqw, 28px); margin-top: 5cqw; }

.pv-game { display: flex; flex-direction: column; align-items: center; height: 100%; padding: 5cqw; gap: 4cqw; background: linear-gradient(180deg, #1b1b3a, #3a2b6b 60%, color-mix(in srgb, var(--pv) 50%, #3a2b6b)); color: #fff; }
.pv-game__hud { width: 100%; display: flex; justify-content: space-between; font-weight: 800; font-size: clamp(12px, 3.6cqw, 16px); opacity: .9; }
.pv-game__stage { position: relative; flex: 1; width: 100%; display: flex; align-items: center; justify-content: center; }
.pv-game__hero { font-size: clamp(54px, 24cqw, 120px); filter: drop-shadow(0 8px 16px rgba(0,0,0,.35)); animation: pv-bob 2.4s ease-in-out infinite; }
.pv-game__rock { position: absolute; font-size: clamp(22px, 8cqw, 40px); }
.pv-game__rock--a { top: 12%; right: 14%; } .pv-game__rock--b { bottom: 16%; left: 12%; }
.pv-game__title { font-family: var(--font-display); font-weight: 600; font-size: clamp(16px, 5cqw, 24px); }
@keyframes pv-bob { 0%,100% { transform: translateY(-6px); } 50% { transform: translateY(6px); } }

.pv-quiz { display: flex; flex-direction: column; height: 100%; padding: 7cqw 6cqw; gap: 4cqw; background: linear-gradient(170deg, color-mix(in srgb, var(--pv) 12%, #fff), #fff); }
.pv-quiz__top { font-weight: 800; font-size: clamp(11px, 3.4cqw, 14px); color: var(--pv); text-transform: uppercase; letter-spacing: .05em; }
.pv-quiz__q { font-family: var(--font-display); font-weight: 600; font-size: clamp(18px, 6cqw, 30px); color: var(--text-strong); display: flex; align-items: center; gap: 10px; }
.pv-quiz__emoji { font-size: 1.3em; }
.pv-quiz__opts { display: flex; flex-direction: column; gap: 3cqw; margin-top: auto; }
.pv-opt { border: 2px solid color-mix(in srgb, var(--pv) 26%, #fff); background: #fff; border-radius: 16px; padding: 4.5cqw; font: inherit; font-weight: 700; font-size: clamp(14px, 4.4cqw, 19px); text-align: left; color: var(--text-strong); cursor: pointer; }
.pv-opt:hover { background: color-mix(in srgb, var(--pv) 8%, #fff); border-color: var(--pv); }
.pv-quiz__title { text-align: center; font-size: clamp(11px, 3.4cqw, 14px); color: var(--text-faint); }

.pv-site { height: 100%; overflow: auto; background: #fff; }
.pv-site__nav { display: flex; align-items: center; justify-content: space-between; padding: 4cqw 5cqw; background: var(--pv); color: #fff; }
.pv-site__brand { font-family: var(--font-display); font-weight: 600; font-size: clamp(13px, 4cqw, 18px); }
.pv-site__links { display: flex; gap: 6px; } .pv-site__links i { width: clamp(14px, 4cqw, 20px); height: 4px; background: rgba(255,255,255,.6); border-radius: 2px; }
.pv-site__hero { padding: 8cqw 5cqw; text-align: center; background: color-mix(in srgb, var(--pv) 10%, #fff); }
.pv-site__h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(20px, 7cqw, 32px); color: var(--text-strong); }
.pv-site__sub { font-size: clamp(12px, 3.8cqw, 16px); color: var(--text-muted); margin-top: 1.5cqw; }
.pv-site__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(40cqw, 1fr)); gap: 3cqw; padding: 5cqw; }
.pv-site__card { border: 1.5px solid var(--border-hairline); border-radius: 14px; padding: 5cqw; text-align: center; }
.pv-site__cardtop { font-size: clamp(30px, 12cqw, 52px); }
.pv-site__cardlabel { font-weight: 700; font-size: clamp(12px, 3.6cqw, 16px); color: var(--text-strong); margin-top: 2cqw; }

/* ── Responsive ──────────────────────────────────────────────── */
@media (max-width: 860px) {
  .pl-app { flex-direction: column; }
  .pl-sidebar { width: 100%; height: auto; position: static; flex-direction: row; align-items: center; gap: 4px; overflow-x: auto; padding: 10px 12px; }
  .pl-brand { padding: 4px 8px; }
  .pl-brand b { display: none; } /* logo only on mobile — free the row for nav */
  .pl-nav { flex-direction: row; }
  .pl-navitem > span:not(.e) { display: none; }
  .pl-navitem { padding: 9px 11px; min-height: 42px; min-width: 42px; justify-content: center; }
  .pl-nav-spacer, .pl-planmini { display: none; }
  .pl-navsep { width: 1px; height: 28px; margin: 0 6px; }
  .pl-kidsnav { flex-direction: row; }
  .pl-kidsnav__label { display: none; }
  .pl-navitem--newkid > span:not(.e) { display: none; }
  .pl-content { padding: 20px 16px 48px; }
  .pl-grid--2, .pl-grid--3 { grid-template-columns: 1fr; }
  .pl-plans { grid-template-columns: 1fr 1fr; }
  .pl-setrow { grid-template-columns: 1fr; gap: 12px; }
  .pl-gchat { height: auto; min-height: 100dvh; }
  .pl-gchat__split { flex-direction: column; }
  .pl-gchat__col { flex: 0 0 auto; }
  .pl-gchat__split > .pl-preview-pane { border-left: 0; border-top: 1px solid var(--border-hairline); min-height: 440px; }
  .pl-railtoggle { display: none; }
}
@media (max-width: 520px) {
  .pl-plans { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .pl-sidebar { transition: none; }
}

/* ── Wonderkit app additions (not in the handoff prototype) ─────────────── */

/* View switching + gate + toast (carried over from the old parent.html
   inline styles; the chat view still uses these). */
.view { display: none; }
.view[data-active="true"] { display: block; }
.gate { padding: 40px; text-align: center; color: var(--text-muted, #475569); }
.toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: #0f172a; color: #fff; padding: 8px 14px; border-radius: 8px; font-size: 13px; opacity: 0; transition: opacity .2s; z-index: 90; pointer-events: none; }
.toast[data-show="true"] { opacity: 1; }
.empty { color: #94a3b8; font-size: 13px; font-style: italic; }

/* Sign-out lives in the sidebar plan card now (the header banner is gone). */
.pl-signout { display: flex; align-items: center; gap: 7px; margin-top: 10px; padding: 0; border: 0; background: none; cursor: pointer; font: 700 12px/1 var(--font-sans); color: var(--text-muted); }
.pl-signout:hover { color: var(--violet-700, #6d28d9); }

/* Operator "Get free credits" invites screen */
.pl-invites { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.pl-invite { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1.5px solid var(--border-card); border-radius: var(--radius-lg); background: var(--white); }
.pl-invite code { font-family: var(--font-mono, ui-monospace, monospace); font-size: 14px; font-weight: 700; letter-spacing: .04em; color: var(--text-strong); }
.pl-invite .wk-btn { margin-left: auto; }
.pl-invite.is-redeemed { opacity: .6; }
.pl-invite__tag { margin-left: auto; font-size: 12px; font-weight: 700; color: var(--text-faint); }

/* Chat-view mode toggle (guardian ↔ Build) reuses the pl-seg control. */
.pl-seg--chatmode { display: inline-flex; }

/* The chat view renders inside the shell's content column but predates the
   portal styles — keep its container full-width. */
/* Full-bleed: the grown-up chat (.pl-gchat) is edge-to-edge per the design —
   no centered max-width column or page margins. */

/* — floating scroll-to-bottom button — */
.pl-scrollbtn {
  position: absolute; left: 50%; bottom: 92px; transform: translateX(-50%) scale(.9);
  width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--border-hairline);
  background: var(--white); color: var(--color-primary-ink); box-shadow: var(--shadow-md);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  opacity: 0; pointer-events: none; transition: opacity var(--dur-base), transform var(--dur-base); z-index: 5;
}
.pl-scrollbtn.is-visible { opacity: 1; pointer-events: auto; transform: translateX(-50%) scale(1); }
.pl-scrollbtn:hover { background: var(--surface-subtle); }
#transcript-view { max-width: none; margin: 0; padding: 0; }

/* ── Touch targets (coarse pointers) ─────────────────────────────
   Meet the 44px minimum on touch devices for the portal's row/toolbar/settings
   controls. Kid-facing composer buttons get the full 44px (children need larger
   targets). Scoped to pointer:coarse so mouse/desktop sizing is unchanged. */
@media (pointer: coarse) {
  .pl-composer__mic, .pl-composer__send { width: 44px; height: 44px; }
  .pl-seg__opt { min-height: 44px; }
  .pl-tab { min-height: 44px; }
  .pl-danger__btn { min-height: 44px; }
  /* Inline pencils: expand the TAP area with an absolute overlay so touch gets a
     ~44px target WITHOUT inflating the text line they sit inside (a width/height
     bump would make the title/name line 44px tall — chunky). */
  .pl-editname, .pl-editname--sm { position: relative; }
  .pl-editname::after, .pl-editname--sm::after { content: ""; position: absolute; inset: -8px; }
}
