/* ==========================================================================
   PAGE HERO — canonical component (csync #2689)
   One hero for every tool page, replacing per-page header forks. Harvested
   from the Bield PageHero pattern (web/components/PageHero.tsx: kicker/title/
   emphasis/subhead/subnote/image/align + dark scrim) and re-themed for Ask
   Olive's own design system — indigo/leaf on near-black, the --thread
   gradient as the recurring motif — rather than Bield's navy+cyan.

   Rendered by public/components/page-hero.js (<page-hero> custom element).
   Tokens consumed here (--bg, --ink, --text, --thread, --scrim, --brand,
   --leaf, --sp-*, --fs-*, --r-lg) come from public/css/ask-olive.css and
   MUST already be on the page — this file styles the component, it does not
   redefine the palette.

   Until a page has a real ComfyUI-generated image, <page-hero> renders a
   CSS-only "thread" placeholder in the ph-group-* variants below — the
   component ships and every page can adopt it BEFORE the image library
   exists (ticket: "build the component first, roll it second").
   ========================================================================== */

.ph {
  --ph-media-w: 44%;
  position: relative;
  display: flex;
  align-items: stretch;
  gap: var(--sp-8, 2rem);
  min-height: 320px;
  margin: 0 0 var(--sp-8, 2rem);
  padding: var(--sp-10, 2.5rem) var(--sp-6, 1.5rem);
  border-radius: var(--r-lg, 14px);
  overflow: hidden;
  background: var(--bg-raised, var(--lq-ground-lift, #14172A));
  isolation: isolate;
}

.ph--align-right { flex-direction: row-reverse; }

.ph-content {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  max-width: 640px;
}

.ph-kicker {
  margin: 0 0 var(--sp-2, 0.5rem);
  font-family: var(--font-mono, monospace);
  font-size: var(--fs-xs, 0.75rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--leaf, var(--lq-ok, #A9C86C));
}

.ph-title {
  margin: 0 0 var(--sp-4, 1rem);
  font-family: var(--font-display, sans-serif);
  font-size: var(--fs-3xl, 2.5rem);
  line-height: var(--lh-tight, 1.15);
  color: var(--ink, var(--lq-text-warm, #F0F2FC));
  font-weight: 700;
}

.ph-title em {
  font-style: normal;
  /* The fallback is load-bearing, not decoration. --thread is defined in
     ask-olive.css, which most pages carrying a <page-hero> do NOT load. Without
     a fallback, `background` resolves to nothing while `color: transparent`
     still applies — so every emphasised word in every such hero renders
     INVISIBLE and the title silently loses its middle clause. Verified
     2026-08-04 on /code/migrations.html and /code/answer-builder.html: both
     computed background-image:none, color:rgba(0,0,0,0). Pages that DO define
     --thread are unaffected; a var() fallback only engages when the token is
     absent. */
  background: var(--thread, linear-gradient(90deg, var(--lq-brand-hi, #8B93F8), var(--lq-ok, #A9C86C)));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.ph-subhead {
  margin: 0 0 var(--sp-2, 0.5rem);
  font-size: var(--fs-md, 1.0625rem);
  line-height: var(--lh-body, 1.6);
  color: var(--text, var(--lq-text-warm, #C9CEE6));
}

.ph-subnote {
  margin: 0;
  font-size: var(--fs-sm, 0.8125rem);
  color: var(--text-muted, var(--lq-text-warm-2, #9BA2C4));
}

.ph-thread-rule {
  height: 2px;
  width: 48px;
  border: 0;
  margin: var(--sp-4, 1rem) 0;
  border-radius: 1px;
  background: var(--thread);
}

/* ---------- media pane ---------- */
.ph-media {
  position: relative;
  flex: 0 0 var(--ph-media-w);
  min-width: 0;
  border-radius: var(--r-md, 10px);
  overflow: hidden;
  background: var(--bg-inset, var(--lq-ground, #090B16));

  /* A DEFINITE height, derived from the width. Without this the pane's height
     comes from the flex row, which on several pages resolves to auto — and a
     child asking for height:100% of an auto-height parent gets `auto` back, so
     the image rendered at its full intrinsic 1200x800 and blew the layout open.
     It looked like a specificity fight with the legacy stylesheets and was not;
     the rule was winning and had nothing to resolve against.
     3/2 matches the generated library (1200x800). */
  aspect-ratio: 3 / 2;
}

/* Absolutely positioned inside the pane rather than sized against it, so the
   image can never contribute to layout no matter what a page's own CSS does to
   the surrounding flex context. .ph-media is already position:relative and
   overflow:hidden, so this is contained by construction. */
.ph-media picture,
.ph-media img {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: 100%;
  object-fit: cover;
}

/* Dark scrim so overlaid/adjacent text keeps AA contrast against whatever
   the generated image turns out to be (ticket constraint #3). */
.ph-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--scrim, rgba(4,5,12,.6)) 0%, transparent 60%);
  pointer-events: none;
}
.ph--align-right .ph-scrim {
  background: linear-gradient(270deg, var(--scrim, rgba(4,5,12,.6)) 0%, transparent 60%);
}

/* ---------- CSS-only placeholder motifs (no image attribute yet) ----------
   One idea per tool-page group so a returning user can tell where they are
   from the shape alone, per the ticket's per-group art direction. These are
   deliberately abstract (filaments/lattice/strata) — never text, never
   people — and get swapped for the ComfyUI plates without changing markup:
   the component just starts rendering a <picture> once `image` is set. */
.ph-media.ph-placeholder { background: var(--bg-inset, var(--lq-ground, #090B16)); }

.ph-media.ph-placeholder::before {
  content: '';
  position: absolute;
  inset: 0;
}

/* ask-discover: fine threads converging to a bright point */
.ph-group-ask .ph-placeholder::before {
  background:
    radial-gradient(circle at 78% 50%, rgba(169,200,108,.35), transparent 42%),
    repeating-linear-gradient(70deg, color-mix(in srgb, var(--lq-brand-hi, #8B93F8) 16%, transparent) 0 1px, transparent 1px 22px);
}

/* process-flow: routed network, nodes and directed paths */
.ph-group-flow .ph-placeholder::before {
  background:
    repeating-linear-gradient(115deg, color-mix(in srgb, var(--lq-brand-hi, #8B93F8) 20%, transparent) 0 2px, transparent 2px 34px),
    repeating-linear-gradient(25deg, rgba(169,200,108,.14) 0 2px, transparent 2px 46px);
}

/* project-delivery: layered translucent strata, cross-section */
.ph-group-project .ph-placeholder::before {
  background: repeating-linear-gradient(180deg,
    color-mix(in srgb, var(--lq-brand-hi, #8B93F8) 22%, transparent) 0 6px, transparent 6px 34px, rgba(169,200,108,.10) 34px 40px, transparent 40px 68px);
}

/* technical-code: dense woven lattice, precision-machined */
.ph-group-technical .ph-placeholder::before {
  background:
    repeating-linear-gradient(0deg, color-mix(in srgb, var(--lq-brand-hi, #8B93F8) 18%, transparent) 0 1px, transparent 1px 14px),
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--lq-brand-hi, #8B93F8) 18%, transparent) 0 1px, transparent 1px 14px);
}

/* docs-training: folded overlapping translucent leaves (paper-like, not literal) */
.ph-group-docs .ph-placeholder::before {
  background:
    repeating-linear-gradient(160deg, rgba(169,200,108,.14) 0 40px, transparent 40px 80px),
    repeating-linear-gradient(200deg, color-mix(in srgb, var(--lq-brand-hi, #8B93F8) 12%, transparent) 0 30px, transparent 30px 90px);
}

/* account-billing-legal: quietest — almost monochrome, single thread */
.ph-group-account .ph-placeholder::before {
  background: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--lq-brand-hi, #8B93F8) 14%, transparent) 48%, transparent 100%);
}

/* ==========================================================================
   COMPACT MODIFIER — project working-page layout (Richard, 2026-08-04:
   "what we are doing now will be the layout"). Once a user is inside a
   project's tools, the hero isn't a landing moment — it's a strip that
   states where you are and hands off immediately to a full-width chat bar
   and the work area. `.ph--compact` is applied by page-hero.js when the
   host page adds the `compact` boolean attribute; nothing else about
   <page-hero> changes, so every other page using the canonical (tall) hero
   is unaffected.
   ========================================================================== */
.ph--compact {
  min-height: 0;
  padding: var(--sp-4, 1rem) var(--sp-6, 1.5rem);
  margin-bottom: var(--sp-4, 1rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-4, 1rem);
}
.ph--compact .ph-content { max-width: none; flex: 1 1 auto; }
.ph--compact .ph-kicker { margin: 0 0 2px; }
.ph--compact .ph-title { margin: 0; font-size: var(--fs-xl, 1.375rem); line-height: 1.25; }
/* No room for the media pane, the thread rule, or a second/third line of
   marketing copy at this height — dropped by the modifier so a compact hero
   is the same height regardless of what a page happens to pass in. */
.ph--compact .ph-media,
.ph--compact .ph-thread-rule,
.ph--compact .ph-subhead,
.ph--compact .ph-subnote { display: none; }

/* The compact "Project / object Olive" chip — STATES scope, doesn't ask for
   input (the actual composer is <olive-ask-bar>, immediately below the
   hero). Text comes from the `olive-scope` attribute, which the host page
   fills from its own real data — this file only lays it out. */
.ph-olive-scope {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 8px;
  border-radius: var(--r-full, 999px);
  background: var(--bg-inset, var(--lq-ground, #0C0E1C));
  border: 1px solid var(--line, var(--lq-rule, #262B45));
}
.ph-olive-scope-icon {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  background: var(--leaf-tint, #1A2114);
  display: flex; align-items: center; justify-content: center;
}
.ph-olive-scope-icon svg { width: 12px; height: 12px; color: var(--leaf, var(--lq-ok, #A9C86C)); }
.ph-olive-scope-text { font: 600 var(--fs-xs, .75rem)/1.3 var(--font-mono, monospace); color: var(--text-muted, var(--lq-text-warm-2, #9BA2C4)); white-space: nowrap; }

@media (max-width: 860px) {
  .ph--compact { flex-direction: column; align-items: flex-start; }
}

/* ---------- responsive ---------- */
@media (max-width: 860px) {
  .ph, .ph--align-right { flex-direction: column; min-height: 0; }
  /* An explicit height replaces the 3/2 ratio here — stacked on a narrow
     screen, a full-width hero at 3:2 would be 240px+ of image before any text. */
  .ph-media { flex-basis: auto; height: 200px; aspect-ratio: auto; }
  .ph-content { max-width: none; }
  .ph-title { font-size: var(--fs-2xl, 1.875rem); }
}

@media (prefers-reduced-motion: no-preference) {
  .ph-media img { transition: transform var(--dur-3, 350ms) var(--ease, ease); }
  .ph:hover .ph-media img { transform: scale(1.02); }
}
