/*
 * Public page compositions (UI-002 home + the shared M11-B2 layered page
 * language every public surface loads). Frozen target:
 * docs/design/ui-references/20260915-m11/index.html — all values resolve to
 * tokens; the documented exceptions are frozen-viewport media conditions and
 * the 2.75rem minimum target. Short rules are single-line to keep this sheet
 * under the 500-line module limit.
 */

/* ---------- base ---------- */

/* Public brand maintenance, 2026-09-26. Status words still carry meaning;
   category and status accents use the same orange/navy palette. Shared
   frozen tokens remain available to the separate admin surface. */
body {
  --color-warning: var(--color-accent-text); --color-warning-soft: var(--color-accent-soft);
  --color-warning-fill: var(--color-accent);
  --color-danger: var(--color-accent-text); --color-danger-soft: var(--color-accent-soft);
  --color-success: var(--color-text); --color-success-soft: var(--color-bg-subtle);
  --color-info: var(--color-text); --color-info-soft: var(--color-bg-subtle);
  --color-focus: var(--color-accent-text); --color-accent-deep: var(--color-text);
}
@media not print { [data-theme="dark"] body {
  --color-accent-soft: var(--color-dark-surface); --shadow-focus: 0 0 0 0.1875rem var(--color-dark-accent-text);
} }

*,
*::before,
*::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}
.public-main { flex: 1 0 auto; }

/*
 * Skip-link destination keeps the solid frozen-token focus ring (same
 * contract as the global :focus-visible indicator; programmatic focus does
 * not always match :focus-visible).
 */
.public-main:focus { outline: 0.1875rem solid var(--color-focus); outline-offset: 0; border-radius: var(--radius-sm); }
img, svg { display: block; max-width: 100%; }

/* heading focus targets (legal TOC anchors): solid frozen-token ring on
   keyboard activation only — mouse clicks on TOC links land focus here
   without painting the ring (:focus-visible heuristic). */
[data-focus-target]:focus-visible { outline: 0.1875rem solid var(--color-focus); outline-offset: 0; border-radius: var(--radius-sm); }

/* ---------- brand mark (DS-005, logo suspended: text wordmark only) ---------- */

.brand-mark { display: inline-flex; align-items: baseline; color: currentColor; }
.brand-mark-word {
  font-family: var(--font-display);
  font-size: var(--text-heading); /* wordmark ≥96px wide per DS-005 */
  font-weight: var(--weight-semibold);
  line-height: 1;
  letter-spacing: 0;
}

/* ---------- button language (M14: reference press primitives, public scope) ---------- */

/*
 * The HiFi reference buttons run radius-sm with the .55rem/1rem rhythm, and
 * its secondary is the OUTLINED form (surface ground, 2px ink frame, no
 * shadow) — the solid navy secondary block stays an admin-sheet treatment.
 * These overrides live on public pages only; the admin shell never loads
 * this sheet. Control selectors stay in this token-source sheet (chrome.css
 * is not a declared primitive source); the rhythm values come from the
 * chrome sheet's self-declared block.
 */
.btn { padding: var(--chrome-btn-pad); border-radius: var(--radius-sm); }
.btn-secondary { background: var(--color-surface); color: var(--color-text); border-color: var(--color-text); box-shadow: none; }
.btn-secondary:hover,
.btn-secondary:active { transform: none; box-shadow: none; }

/* M12 (UX-010), kept under the M14 reference box: at 320x568 the stacked
   banner rose ~52px past the hero CTA; the two actions share one 44px row. */
@media (max-width: 47.99rem) {
  .consent-actions .btn { inline-size: 100%; min-inline-size: 0; white-space: normal; }
}

/* ---------- shared M11-B2 layered page language (UI-002..UI-021 heads) ----------
   Frozen port of the reference's layered head: six-column hairline grid,
   outline ghost glyph, hairline baseline, vertical mono margin note, kicker
   rule, display page head, section head, mono chips and the press-card row. */

.tag { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--color-text-muted); }
.layered { position: relative; overflow: hidden; padding: 3.2rem 0 2rem; }
/* Frozen per-surface head rhythm (the reference carries these inline on each
   layered head): the 3.2rem/2rem base is the modal head (UI-016/018/020);
   the modifiers below keep each surface's own frozen measure. */
.layered-coming-soon { padding: 4.2rem 0 3.4rem; min-height: 18rem; }
.layered-coming-soon .container { padding-bottom: 3.4rem; }
.layered-legal { padding: 3.2rem 0 2.2rem; }
.layered-method { padding: 3.6rem 0 2.6rem; }
.layered-detail { padding: 2.8rem 0 1.8rem; }
.layered-article { padding: 3rem 0 1.8rem; }
.layered .grid-bg { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(6, 1fr); pointer-events: none; }
.layered .grid-bg i { border-left: 1px solid var(--color-border); }
.layered .grid-bg i:first-child { border-left: 0; }
/* The ghost base serves the layered heads and the home hero alike; each
   region overrides its own scale. */
.layered .ghost,
.hero .ghost {
  position: absolute;
  right: -0.5rem;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: transparent;
  -webkit-text-stroke: 2px var(--color-ghost);
  user-select: none;
  pointer-events: none;
}

.layered .ghost { top: 0.8rem; font-size: clamp(9rem, 20vw, 17rem); }
.layered .baseline { position: absolute; left: 0; right: 0; bottom: 0; border-bottom: 1px solid var(--color-border); pointer-events: none; }
.layered .mnote {
  position: absolute;
  left: -0.4rem;
  top: 6rem;
  writing-mode: vertical-rl;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.34em;
  color: var(--color-border-strong);
}
.mnote b { color: var(--color-accent-text); font-weight: var(--weight-semibold); }
.kicker { display: flex; align-items: center; gap: 0.9rem; margin-bottom: 1.2rem; }
.kicker::after { content: ""; flex: 1; border-top: 1px solid var(--color-border-strong); }
.page-head h1 {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: clamp(2.1rem, 4.6vw, 3.4rem);
  line-height: 1.12;
  letter-spacing: -0.025em;
  position: relative;
}
.page-head h1 em { font-style: normal; color: var(--color-accent); }
.page-head .sub { margin-top: 1rem; font-size: 1.05rem; color: var(--color-text-muted); max-width: 38ch; }
.block { padding: 2.6rem 0; }
.sec-head { margin: 0 0 1.6rem; }
.sec-head h2 { font-family: var(--font-display); font-size: 1.5rem; font-weight: var(--weight-bold); margin-top: 0.25rem; }
.chips { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.chip {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  border: 1px solid var(--color-border-strong);
  padding: 0.3rem 0.8rem;
  color: var(--color-text);
  background: var(--color-bg);
  text-decoration: none;
}
.chip b { color: var(--color-accent-text); font-weight: var(--weight-semibold); }

/* The blog filter row's group divider (reference renders the same 1px
   stretch span inline between the column and author chip groups). */
.chip-divider { width: 1px; background: var(--color-border-strong); align-self: stretch; }
.cardgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.6rem; }
.press-card { text-decoration: none; display: block; border-top: 2px solid var(--color-text); padding-top: 0.9rem; color: inherit; }
.press-card:hover h2 { color: var(--color-accent-text); }
.press-card .no { font-family: var(--font-mono); color: var(--color-accent-text); font-size: 0.82rem; }
.press-card h2 { font-size: 1.05rem; line-height: 1.45; margin: 0.5rem 0 0.6rem; font-weight: var(--weight-semibold); }
.press-card .meta { font-size: 0.76rem; color: var(--color-text-muted); display: flex; gap: 0.6rem; align-items: center; }
.press-card .meta > span { white-space: nowrap; }
.ai-note { border: 1px solid var(--color-border-strong); color: var(--color-text-muted); font-size: 0.7rem; padding: 0.06rem 0.45rem; }
.empty-note {
  border: 1px dashed var(--color-border-strong);
  padding: 1.8rem 1.4rem;
  color: var(--color-text-muted);
  font-family: var(--font-mono);
  font-size: 0.85rem;
}
.proof-line { font-family: var(--font-mono); font-size: 0.78rem; color: var(--color-text-muted); }
.proof-line b { color: var(--color-text); white-space: nowrap; }
.nw-date { white-space: nowrap; }
.proof-line .dot { color: var(--color-accent); }
/* Warning-tone flag (legal review-pending); the neutral data-recency note
   is .update-flag. */
.stale-flag { font-family: var(--font-mono); font-size: 0.74rem; margin-top: 0.5rem; color: var(--color-accent-text); }
/* Neutral update note (owner revision 2026-09-21, R6/R7): the pages state
   when their data refreshes instead of warning about real-time-ness. */
.update-flag { font-family: var(--font-mono); font-size: 0.74rem; margin-top: 0.5rem; color: var(--color-text-muted); }

/* ---------- home hero (UI-002 layered editorial composition) ---------- */

.hero { position: relative; padding: 4.6rem 0 4rem; overflow: hidden; }
.hero-grid { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(6, 1fr); pointer-events: none; }
.hero-grid i { border-left: 1px solid var(--color-border); }
.hero-grid i:first-child { border-left: 0; }
.hero-scan {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: var(--color-border-strong);
  opacity: 0;
  pointer-events: none;
  animation: hero-scan 9s linear 1.6s infinite;
}

@keyframes hero-scan {
  0% { top: 0; opacity: 0; }
  4% { opacity: 0.5; }
  50% { opacity: 0.5; }
  96% { opacity: 0.5; }
  100% { top: calc(100% - 1px); opacity: 0; }
}
.hero-baseline { position: absolute; left: 0; right: 0; bottom: 0; border-bottom: 1px solid var(--color-border); pointer-events: none; }
.hero .ghost {
  top: 1.2rem;
  font-size: clamp(11rem, 26vw, 22rem);
  animation: ghost-in 0.9s var(--ease-enter) both, ghost-drift 26s ease-in-out 1.2s infinite alternate;
}

@keyframes ghost-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes ghost-drift { from { transform: translate(0, 0); } to { transform: translate(-1.5%, -1%); } }

.margin-note {
  position: absolute;
  left: -0.4rem;
  top: 6.5rem;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.34em;
  color: var(--color-border-strong);
}
.margin-note b { color: var(--color-accent-text); font-weight: var(--weight-semibold); }
.hero-inner { position: relative; }
.hero .kicker { margin-bottom: 1.5rem; }

/* The kicker's rule draws in once on load (frozen one-shot; the reduced
   motion guard below renders it static). */
.hero .kicker::after { transform-origin: left center; animation: kicker-draw 0.65s var(--ease-enter) 0.1s both; }

@keyframes kicker-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.hero-title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: clamp(3rem, 8vw, 5.8rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  color: var(--color-text);
}

/* The frozen en reference runs its own display scale for the longer H1. */
.hero-title-locale-en { font-size: clamp(2.4rem, 7vw, 4.4rem); letter-spacing: -0.015em; }

/* DS-006 per-locale display measures (UI review P1): en at the 16ch display
   measure, zh em-exact for CJK — the longest unbreakable frozen run is the
   5-glyph tail 看清。 compound, so 5em admits exactly that line. The zh tail
   is one unbreakable unit: the em (用數據) is an atomic inline box and the
   rule-under span (看清) is nowrap — measured Chrome 153, the atomic em
   alone still split at the legal 看|清 break inside the span and stranded
   清。 (排版盤點 2026-09-25 #3); with the span atomic, 。 may not begin a
   line, so the last admissible break is the em boundary and the tail line
   reads 看清。 (balance was rejected: it re-wraps the h1a half too). */
.hero-title-locale-en { max-width: var(--size-measure-display-en); }
.hero-title-locale-zh { max-width: 5em; }
.hero-title-locale-zh em { display: inline-block; }
.hero-title-locale-zh .rule-under { white-space: nowrap; }
.hero-title em { font-style: normal; color: var(--color-accent); }
.hero-title .rule-under { box-shadow: inset 0 -0.16em 0 var(--color-accent-soft); }
.support { margin-top: 1.5rem; font-size: 1.12rem; color: var(--color-text-muted); max-width: 36ch; }
.hero .chips { margin-top: 1.9rem; }
.hero .proof-line { margin-top: 1.7rem; }

/* ---------- home coverage entry cards (PRD-054) + insights (PRD-055) ---------- */

.home-explore,
.insights-sec { padding: 3.4rem 0; }
.home-explore .sec-head,
.insights-sec .sec-head { margin: 0 0 2.2rem; }
.home-explore .sec-head h2,
.insights-sec .sec-head h2 { font-size: 1.7rem; }
/* The five coverage cards are the site's whole category index: one desktop
   row reads as one complete set (narrower breakpoints reflow below). */
.cards { display: grid; grid-template-columns: repeat(5, 1fr); gap: 2.6rem 2rem; }
.card { text-decoration: none; color: inherit; }
.card .big {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 4.2rem;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--color-accent);
  font-variant-numeric: tabular-nums;
}
.card .big small {
  font-size: 1.05rem;
  color: var(--color-text-muted);
  font-weight: var(--weight-regular);
  font-family: var(--font-body);
  letter-spacing: 0;
}
/* Desktop 5-up row: the two long en names wrap to two lines, so the name
   area reserves that measure and every card's sub line starts level (UX
   refine residual 2026-09-24); the narrow breakpoints reset it below. */
.card .name { font-weight: var(--weight-semibold); font-size: 1.05rem; line-height: var(--leading-label); min-height: 3em; margin-top: 0.45rem; color: var(--color-text); }
.card .sub { font-size: 0.82rem; color: var(--color-text-muted); }
.card.soon .big { color: var(--color-text-muted); }
.card:hover .name { color: var(--color-accent-text); }
/* Clickable category cards carry a persistent entry arrow (the .all-link
   language); a.card excludes the non-clickable .card.soon div. */
a.card .name::after { content: "→"; margin-left: 0.4rem; color: var(--color-accent-text); }
.press { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; }

/* The home variant carries the h3 card title and the wider reference rhythm. */
.insights-cards .press-card { padding-top: 1rem; }
.insights-cards .press-card h3 {
  font-size: 1.12rem;
  line-height: 1.45;
  margin: 0.55rem 0 0.7rem;
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  transition: color 0.18s;
}
.insights-cards .press-card:hover h3 { color: var(--color-accent-text); }
.insights-cards .press-card .meta { font-size: 0.78rem; flex-wrap: wrap; }
.all-link {
  display: inline-block;
  margin-top: 2rem;
  font-weight: var(--weight-semibold);
  color: var(--color-accent-text);
  text-decoration: none;
  border-bottom: 2px solid var(--color-accent);
  padding-bottom: 0.12rem;
}
.insights-empty {
  border: 1px dashed var(--color-border-strong);
  padding: 2rem 1.5rem;
  color: var(--color-text-muted);
  font-family: var(--font-mono);
  font-size: 0.85rem;
}

/* The teaser band keeps the container measure (production wraps it in the
   content container; the reference draws it full-bleed). */
.teaser { border-block: 1px solid var(--color-border-strong); padding: 1.6rem 0; display: flex; align-items: baseline; gap: 1.4rem; flex-wrap: wrap; }
.teaser b { font-family: var(--font-display); font-size: 1.3rem; color: var(--color-text); }
.teaser .soon {
  background: var(--color-action-accent);
  color: var(--color-accent-ink);
  font-size: 0.72rem;
  font-weight: var(--weight-bold);
  padding: 0.14rem 0.55rem;
}
.teaser .note { color: var(--color-text-muted); }

/* ---------- responsive reflow (frozen reference breakpoints) ---------- */

@media (max-width: 1024px) {
  .cards { grid-template-columns: repeat(2, 1fr); }
  .card .name { min-height: auto; }
  .press { grid-template-columns: 1fr; }
  .cardgrid { grid-template-columns: repeat(2, 1fr); }
  .hero .ghost { font-size: 34vw; top: 0.5rem; }
}

@media (max-width: 640px) {
  .cards { grid-template-columns: 1fr; }
  .cardgrid { grid-template-columns: 1fr; }
  .hero { padding: 3rem 0 2.6rem; }
  .margin-note { display: none; }
  .layered .mnote { display: none; }
  .hero-grid { grid-template-columns: repeat(3, 1fr); }
  .layered .grid-bg { grid-template-columns: repeat(3, 1fr); }
  /* At phone widths the 30vw glyph still spans the whole head and its
     stroke crosses the breadcrumb/kicker lines; half-strength keeps the
     layered texture without fighting the small mono text. */
  .layered .ghost { font-size: 30vw; opacity: 0.5; }
}

/* ---------- coming soon ---------- */

.coming-soon-panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
  padding-block: var(--space-10);
  max-width: var(--size-container-narrow);
  margin-inline: auto;
}
.coming-soon-purpose { margin: 0; max-width: var(--size-measure-body); }
.coming-actions { margin: 1.8rem 0 0; }

/* ---------- micro-interactions (E1 P1) ---------- */

/*
 * State feedback for the surfaces the component sheets leave static: the
 * product/content card family lifts on hover, the public button family
 * answers a press, and chips/links fade their state swaps. Transform- and
 * paint-only properties (no layout properties, so nothing reflows), run at
 * the frozen 120ms fast duration on the frozen standard easing. The
 * reduced-motion guard below collapses the transitions and keeps no travel.
 */

/* card family (.list-card / .article-card, the VD-R4-02
   ink-frame cards): hover lifts 2px, deepens the hard-offset press shadow
   one step (5px to 7px) and shifts the frame to the coral signal; hover-gated
   so touch devices never see a stuck lift. The product list left this family
   with the card grid (橫列式列表 2026-09-24): the full-width rows answer the
   hover with their 3px left bar turning accent — no lift, no shadow. */
@media (hover: hover) {
  .list-card,
  .article-card {
    transition: transform var(--duration-fast) var(--ease-standard),
      box-shadow var(--duration-fast) var(--ease-standard),
      border-color var(--duration-fast) var(--ease-standard);
  }
  .list-card:hover,
.article-card:hover { transform: translateY(-2px); box-shadow: 0.4375rem 0.4375rem 0 var(--color-text); border-color: var(--color-accent); }
}

/* pressed answer for the outlined public secondary (its flat reference hover
   stays): 1px settle with the hard-offset shadow tightened to the 3px depth
   the solid variants use on hover; the solid primary/secondary keep their
   deeper 5px press from controls.css */
.btn-secondary:active { transform: translateY(0.0625rem); box-shadow: 0.1875rem 0.1875rem 0 var(--color-text); }

/* chips and links fade their state swaps: the chip fill shift, the nav link
   ink shift and the footer link underline thickening to the coral rule */
.filter-chip {
  transition: background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}
.nav-link {
  transition: color var(--duration-fast) var(--ease-standard),
    text-decoration-color var(--duration-fast) var(--ease-standard),
    text-decoration-thickness var(--duration-fast) var(--ease-standard);
}

/* ---------- reduced motion (frozen variant `none`) ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* E1 P1: the micro-interaction layer answers instantly — transitions
     collapse and the hover lift / press settle keep no travel (the paint-only
     border, shadow and color states still change, with no motion). The .btn
     kill sits here, after controls.css, because the primitives guard's
     `.btn { transition: none }` loses the cascade to the controls base
     transition (primitives loads first) and never applied. */
  .list-card,
  .article-card,
  .home-teaser-card,
  .filter-chip,
  .nav-link,
  .btn,
  .btn-secondary:active,
  .press-card h3 {
    transition: none;
  }
  .list-card:hover,
  .article-card:hover,
  .btn-secondary:active {
    transform: none;
  }

  /* UI-002 ambient layers collapse to the static composition: the scan line
     never paints, the ghost and kicker rule render at full opacity. */
  .hero-scan { display: none; }
  .hero .ghost,
  .hero .kicker::after { animation: none; }
}

/* ---------- print (legal surfaces) ---------- */

@media print {
  .public-header,
  .public-footer,
  .skip-link,
  [data-print-action],
  .toc { display: none !important; }

  /* Review 2026-09-14: a print before the scroll-reveal regions entered the
     viewport must still print them — the pending state is a screen-only
     pre-roll, never a print state. */
  .motion-reveal-pending,
  .motion-reveal-pending > * { opacity: 1; }

  /* Paper always gets the frozen light pair: the canonical tokens resolve
     there because the dark remap in tokens.css is scoped to `not print`. */
  body { background: var(--color-surface); color: var(--color-text); }
}
