/* SmartPropFact components — the render layer on the tokens (Arc 1 Task 2).
   Consumes /static/tokens.css only: every color, radius, spacing and type size is a var(--…);
   no hex, no rgb literals, no Tailwind. Dark mode arrives through the tokens (data-theme on <html>);
   the [data-theme="dark"] rules below exist only where DESIGN.md says depth differs
   (surface step + inner hairline + top glow instead of the drop shadow).
   Survives the Tailwind preflight that still loads for unmigrated screens: explicit
   box-sizing, button resets, svg display. */

/* ---------- base + resets ---------- */
[class*="spf-"], [class*="spf-"] * { box-sizing: border-box; }
.spf-btn, .spf-seg-opt, .spf-sheet-close, button.spf-row {
  appearance: none; -webkit-appearance: none; border: 0; margin: 0; padding: 0; background: none;
  font: inherit; color: inherit; text-align: inherit; cursor: pointer; text-decoration: none;
}
.spf-num { font-variant-numeric: tabular-nums lining-nums; font-feature-settings: "tnum" 1; }
.spf-hero, .spf-card, .spf-row, .spf-chip, .spf-btn, .spf-seg, .spf-ring, .spf-stat,
.spf-skel, .spf-empty, .spf-sheet, .spf-title, .spf-note {
  font-family: var(--font-sans); color: var(--text); line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}
/* `> svg` on the card: a chart dropped straight into a card is a block, but a row's or a
   button's icon nested inside it keeps its inline rule instead of relying on source order */
.spf-hero svg, .spf-card > svg, .spf-ring svg { display: block; }
.spf-row svg, .spf-btn svg { display: inline-block; vertical-align: middle; }
.spf-chev { display: inline-block; vertical-align: middle; }
.spf-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--text-3);
}

/* tone → color on the dot / figure / stroke (DESIGN.md §Color — meanings are law) */
[data-tone="equity"] > .spf-dot, [data-tone="ok"] > .spf-dot { background: var(--equity); }
[data-tone="cash"] > .spf-dot { background: var(--cash); }
[data-tone="cash-deductible"] > .spf-dot { background: var(--cash-deductible); }
[data-tone="taxable"] > .spf-dot, [data-tone="warn"] > .spf-dot { background: var(--taxable); }
[data-tone="drag"] > .spf-dot { background: var(--drag); }
[data-tone="market"] > .spf-dot, [data-tone="info"] > .spf-dot { background: var(--market); }
[data-tone="muted"] > .spf-dot { background: var(--text-3); }

/* ---------- hero (navy in both modes; never inverted) ---------- */
.spf-hero {
  /* hero-scoped: the navy card keeps the dark-tuned semantics in both modes (tokens.css --hero-*),
     so a chip / glow inside it is the same chip in light and dark. The tint tokens are re-mixed
     here because a :root-level color-mix() has already resolved --equity at :root. */
  --equity: var(--hero-equity); --drag: var(--hero-drag); --cash: var(--hero-cash); --taxable: var(--hero-taxable);
  --market: var(--hero-market); --cash-deductible: var(--hero-cash-deductible);
  --taxable-text: var(--hero-taxable);
  --equity-tint: color-mix(in srgb, var(--equity) 20%, transparent);
  --drag-tint: color-mix(in srgb, var(--drag) 22%, transparent);
  --cash-tint: color-mix(in srgb, var(--cash) 14%, transparent);
  --taxable-tint: color-mix(in srgb, var(--taxable) 22%, transparent);
  --market-tint: color-mix(in srgb, var(--market) 22%, transparent);
  position: relative; overflow: hidden;
  border-radius: var(--r-hero); padding: 20px 20px var(--sp-4);
  background: var(--hero-bg); color: var(--hero-text);
  box-shadow: var(--shadow-card);
}
.spf-hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(180px 180px at 92% 4%,
    color-mix(in srgb, var(--equity) 30%, transparent), transparent 70%);
}
.spf-hero > * { position: relative; }
.spf-hero-lbl { font-size: var(--fs-micro); font-weight: 500; color: var(--hero-text-2); letter-spacing: .01em; word-break: keep-all; }
.spf-hero-fig {
  font-size: var(--fs-hero); font-weight: 700; letter-spacing: -.03em; line-height: 1.15;
  margin-top: 2px; white-space: nowrap; color: var(--hero-text);
}
.spf-hero-sent { margin: 10px 0 0; font-size: var(--fs-body); font-weight: 500; color: var(--hero-text); opacity: .9; letter-spacing: -.005em; }
.spf-hero-body { margin-top: var(--sp-3); }
.spf-chips { display: flex; gap: var(--sp-2); margin-top: 10px; flex-wrap: wrap; }
/* the tone chips inside the hero use the plain .spf-chip[data-tone] rules on the re-scoped tokens;
   only the muted chip is hero-specific: DESIGN.md "chips at 20% white" (the mockup's .chip.white) */
.spf-hero .spf-chip[data-tone="muted"] {
  background: color-mix(in srgb, var(--hero-text) 20%, transparent); color: var(--hero-text);
  box-shadow: none;
}
:root[data-theme="dark"] .spf-hero {
  box-shadow: var(--shadow-card),
    inset 0 0 0 1px color-mix(in srgb, var(--hero-text) 8%, transparent),
    inset 0 1px 0 color-mix(in srgb, var(--hero-text) 10%, transparent);
}

/* ---------- cards ---------- */
.spf-card {
  display: block; background: var(--surface); border-radius: var(--r-card);
  box-shadow: var(--shadow-card); padding: var(--sp-4) 18px 18px; margin: 0;
}
.spf-card + .spf-card, .spf-hero + .spf-card, .spf-card + .spf-hero { margin-top: var(--sp-4); }
.spf-card-h { margin: 0 0 var(--sp-1); font-size: var(--fs-body); font-weight: 600; letter-spacing: -.01em; }
:root[data-theme="dark"] .spf-card {
  box-shadow: var(--shadow-card), inset 0 0 0 1px var(--hairline),
    inset 0 1px 0 color-mix(in srgb, var(--text) 5%, transparent);
  background-image: linear-gradient(180deg,
    color-mix(in srgb, var(--text) 4%, transparent), transparent 38%);
}

/* the ①②③ answer card (2-col grid on the home: minmax(0,1fr)) */
.spf-answer { min-width: 0; padding: var(--sp-4) 13px 14px; }
.spf-answer-ttl {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--fs-micro); font-weight: 600; color: var(--text-2); letter-spacing: -.005em; white-space: nowrap;
}
.spf-answer-fig {
  font-size: var(--fs-figure); font-weight: 700; letter-spacing: -.035em; line-height: var(--lh-tight);
  margin-top: 6px; white-space: nowrap; color: var(--text);
}
.spf-answer[data-tone="equity"] .spf-answer-fig, .spf-answer[data-tone="ok"] .spf-answer-fig { color: var(--equity); }
.spf-answer[data-tone="taxable"] .spf-answer-fig, .spf-answer[data-tone="warn"] .spf-answer-fig { color: var(--taxable-text); }
.spf-answer[data-tone="market"] .spf-answer-fig, .spf-answer[data-tone="info"] .spf-answer-fig { color: var(--market); }
.spf-answer[data-tone="cash"] .spf-answer-fig { color: var(--cash); }
.spf-answer[data-tone="cash-deductible"] .spf-answer-fig { color: var(--cash-deductible); }
.spf-answer[data-tone="drag"] .spf-answer-fig { color: var(--drag); }
.spf-answer[data-tone="muted"] .spf-answer-fig { color: var(--text-2); }
/* the answer card's dot sits one level deeper than the [data-tone] section (inside .spf-answer-ttl),
   so the `>` rules above cannot reach it — the tone has to be spelled out at this depth */
.spf-answer[data-tone="equity"] .spf-dot, .spf-answer[data-tone="ok"] .spf-dot { background: var(--equity); }
.spf-answer[data-tone="cash"] .spf-dot { background: var(--cash); }
.spf-answer[data-tone="cash-deductible"] .spf-dot { background: var(--cash-deductible); }
.spf-answer[data-tone="taxable"] .spf-dot, .spf-answer[data-tone="warn"] .spf-dot { background: var(--taxable); }
.spf-answer[data-tone="drag"] .spf-dot { background: var(--drag); }
.spf-answer[data-tone="market"] .spf-dot, .spf-answer[data-tone="info"] .spf-dot { background: var(--market); }
.spf-answer[data-tone="muted"] .spf-dot { background: var(--text-3); }
.spf-pre { font-size: var(--fs-label); font-weight: 600; letter-spacing: 0; margin-right: 1px; }
.spf-answer-mini { margin-top: 10px; }
.spf-answer-mini svg { display: block; width: 100%; height: 30px; }
.spf-answer-sent {
  margin: 6px 0 0; font-size: var(--fs-micro); font-weight: 500; color: var(--text-2); line-height: var(--lh-body);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- list card + rows (Wallet / Health) ---------- */
.spf-list { padding-top: var(--sp-1); padding-bottom: var(--sp-1); }
.spf-list .spf-card-h { padding-top: var(--sp-3); margin-bottom: 0; }
.spf-row {
  display: flex; align-items: center; gap: var(--sp-3); width: 100%;
  padding: var(--sp-3) 0; position: relative; min-height: 44px;
}
.spf-row + .spf-row::before {
  content: ""; position: absolute; left: 22px; right: 0; top: 0; height: 1px; background: var(--hairline);
}
.spf-row > .spf-dot { width: 10px; height: 10px; }
.spf-row-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; text-align: left; }
.spf-row-t {
  font-size: 14px; font-weight: 600; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; word-break: keep-all;
}
.spf-row-s { font-size: var(--fs-micro); font-weight: 500; color: var(--text-2); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.spf-row[data-tone="drag"] .spf-row-s { color: var(--drag); }
.spf-row-v { flex: none; font-size: var(--fs-body); font-weight: 700; letter-spacing: -.02em; white-space: nowrap; }
.spf-row .spf-chev { color: var(--text-3); flex: none; }
button.spf-row:active { opacity: .7; }

/* ---------- chip (pill on the tint tokens) ---------- */
.spf-chip {
  display: inline-flex; align-items: center; gap: var(--sp-1); height: 26px; padding: 0 10px;
  border-radius: var(--r-chip); font-size: var(--fs-micro); font-weight: 600;
  letter-spacing: -.005em; white-space: nowrap; flex: none;
}
.spf-chip[data-tone="equity"], .spf-chip[data-tone="ok"] { background: var(--equity-tint); color: var(--equity); }
.spf-chip[data-tone="taxable"], .spf-chip[data-tone="warn"] { background: var(--taxable-tint); color: var(--taxable-text); }
.spf-chip[data-tone="drag"] { background: var(--drag-tint); color: var(--drag); font-weight: 700; }
.spf-chip[data-tone="market"], .spf-chip[data-tone="info"] { background: var(--market-tint); color: var(--market); }
.spf-chip[data-tone="cash"] { background: var(--cash-tint); color: var(--cash); }
.spf-chip[data-tone="cash-deductible"] { background: var(--cash-tint); color: var(--cash-deductible); }
.spf-chip[data-tone="muted"] { background: var(--surface-2); color: var(--text-2); box-shadow: inset 0 0 0 1px var(--hairline); }
.spf-row .spf-chip { height: 28px; padding: 0 var(--sp-3); }

/* ---------- buttons ---------- */
.spf-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 44px; padding: 0 20px; border-radius: var(--r-control);
  font-size: var(--fs-body); font-weight: 600; letter-spacing: -.005em; white-space: nowrap;
}
.spf-btn[data-kind="primary"] { min-height: 52px; background: var(--tint); color: var(--on-tint); box-shadow: var(--shadow-card); }
.spf-btn[data-kind="secondary"] { background: var(--surface-2); color: var(--text); box-shadow: inset 0 0 0 1px var(--hairline); }
.spf-btn[data-kind="link"] { background: none; color: var(--tint); padding: 0 var(--sp-1); box-shadow: none; }
.spf-btn:active { opacity: .8; }
.spf-btn:focus-visible, .spf-seg-opt:focus-visible, button.spf-row:focus-visible, .spf-sheet-close:focus-visible {
  outline: 2px solid var(--market); outline-offset: 2px;
}

/* ---------- segmented control ---------- */
.spf-seg {
  display: flex; gap: var(--sp-1); padding: var(--sp-1); border-radius: var(--r-control);
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--hairline);
}
.spf-seg-opt {
  flex: 1; min-width: 0; height: 36px; display: flex; align-items: center; justify-content: center;
  border-radius: 12px; font-size: var(--fs-micro); font-weight: 600; color: var(--text-2); white-space: nowrap;
}
.spf-seg-opt[data-selected] { background: var(--tint); color: var(--on-tint); }

/* ---------- 自走 ring ---------- */
.spf-ring { position: relative; flex: none; }
/* the ring's SVG is a chart (agent/charts.py ring_svg, rendered aria-hidden): charts.css owns
   its stroke, from the tone-* class the shape carries. This file owns the box it fills — and
   the immunity below. */
.spf-ring .spf-chart { width: 100%; height: 100%; }
/* cascade immunity. charts.css (loaded AFTER this file) fills a chart shape only through
   .fill-* , which a SOLID shape carries and these outline circles never do; they ship
   fill="none" as an attribute. Pin it here too, at a specificity charts.css cannot beat
   (0,2,1 — two classes and an element), so a later `.tone-* { fill }` rule over there can
   never paint the arc solid inside the ring. */
.spf-ring svg [data-role="ring-arc"], .spf-ring svg [data-role="ring-track"] { fill: none; }
.spf-ring-c {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.spf-ring-pct { font-size: 26px; font-weight: 700; letter-spacing: -.03em; line-height: 1; color: var(--text); }
.spf-ring-sub { font-size: 11px; font-weight: 500; color: var(--text-2); margin-top: var(--sp-1); word-break: keep-all; }

/* ---------- stat (label / value) ---------- */
.spf-stat { display: flex; align-items: center; gap: 10px; min-width: 0; }
.spf-stat-k { flex: 1; min-width: 0; font-size: var(--fs-label); font-weight: 500; color: var(--text-2); word-break: keep-all; }
/* the value never wraps, so an over-long one (the 設定 account line is an email
   address the server never sees the length of) must clip, not push the label out */
.spf-stat-v {
  font-size: 16px; font-weight: 700; letter-spacing: -.02em; color: var(--text);
  white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
/* stacked in one card (設定: account over version, then sign-out) they must not touch —
   the same adjacency idiom as .spf-card + .spf-card */
.spf-stat + .spf-stat, .spf-stat + .spf-btn { margin-top: var(--sp-3); }

/* ---------- skeleton (every async region; no dead taps) ---------- */
.spf-skel { display: flex; flex-direction: column; gap: 10px; border-radius: var(--r-card); }
.spf-skel[data-kind="card"] { padding: var(--sp-4) 18px 18px; background: var(--surface); box-shadow: var(--shadow-card); }
.spf-skel[data-kind="row"] { padding: var(--sp-3) 0; flex-direction: row; align-items: center; }
.spf-skel[data-kind="chart"] { padding: 0; }
.spf-skel-bar {
  display: block; height: 12px; border-radius: var(--r-thumb);
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--text) 6%, transparent) 25%,
    color-mix(in srgb, var(--text) 12%, transparent) 50%,
    color-mix(in srgb, var(--text) 6%, transparent) 75%);
  background-size: 200% 100%;
  animation: spf-shimmer 1.4s ease-in-out infinite;
}
.spf-skel[data-kind="card"] .spf-skel-bar-0 { width: 40%; }
.spf-skel[data-kind="card"] .spf-skel-bar-1 { width: 70%; height: 22px; }
.spf-skel[data-kind="card"] .spf-skel-bar-2 { width: 55%; }
.spf-skel[data-kind="row"] .spf-skel-bar-0 { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.spf-skel[data-kind="row"] .spf-skel-bar-1 { flex: 1; height: 14px; }
.spf-skel[data-kind="chart"] .spf-skel-bar-0 { height: 120px; border-radius: var(--r-control); }
@keyframes spf-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ---------- empty state ---------- */
.spf-empty { text-align: center; padding: var(--sp-8) var(--sp-4); }
.spf-empty-sent { margin: 0; font-size: var(--fs-body); font-weight: 500; color: var(--text-2); line-height: var(--lh-body); }
.spf-empty-act { margin-top: var(--sp-4); display: flex; justify-content: center; }

/* ---------- bottom sheet (tap-to-close in v1; see components.py for the app.js contract) ---------- */
.spf-sheet { position: fixed; inset: 0; z-index: 40; }
.spf-sheet[hidden] { display: none !important; }
.spf-sheet-backdrop { position: absolute; inset: 0; background: color-mix(in srgb, var(--text) 42%, transparent); }
.spf-sheet-panel {
  position: absolute; left: 0; right: 0; bottom: 0; max-height: calc(100% - 56px);
  display: flex; flex-direction: column; background: var(--surface); color: var(--text);
  border-radius: var(--r-hero) var(--r-hero) 0 0; box-shadow: var(--shadow-card);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  animation: spf-sheet-up 320ms ease-out;
}
:root[data-theme="dark"] .spf-sheet-panel {
  box-shadow: var(--shadow-card), inset 0 1px 0 color-mix(in srgb, var(--text) 8%, transparent);
}
.spf-sheet-grabber { width: 36px; height: 5px; border-radius: 3px; background: var(--text-3); opacity: .45; margin: var(--sp-2) auto 0; flex: none; }
.spf-sheet-hdr { display: flex; align-items: center; gap: 10px; padding: 10px var(--gutter) var(--sp-3); flex: none; }
.spf-sheet-title { margin: 0; flex: 1; min-width: 0; font-size: var(--fs-title); font-weight: 600; letter-spacing: -.025em; line-height: var(--lh-tight); }
.spf-sheet-close {
  margin-left: auto; width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2); color: var(--text-2); box-shadow: inset 0 0 0 1px var(--hairline);
  font-size: 18px; line-height: 1; position: relative;
}
.spf-sheet-close::after { content: ""; position: absolute; inset: -6px; }  /* 32px visual, 44px tap target */
.spf-sheet-body { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 0 var(--gutter) 40px; -webkit-overflow-scrolling: touch; }
.spf-sheet-body .spf-card { background: var(--surface-2); box-shadow: none; }
:root[data-theme="dark"] .spf-sheet-body .spf-card { box-shadow: inset 0 0 0 1px var(--hairline); background-image: none; }
@keyframes spf-sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* ---------- text ---------- */
.spf-title {
  margin: 18px 0 0; font-size: var(--fs-label); font-weight: 600; letter-spacing: -.005em; color: var(--text); word-break: keep-all;
}
.spf-note { margin: 20px 0 0; text-align: center; font-size: 11px; font-weight: 500; color: var(--text-3); }

/* ---------- motion (DESIGN.md: enter ease-out · exit ease-in; reduced motion = off) ---------- */
/* the arc draws in from empty on load (no `to`: the stroke-dashoffset attribute supplies the end).
   The `from` is the ring circumference — NOT typed here: components.ring() prints
   charts.ring_circumference() onto the wrapper as --spf-ring-c, the arc inherits it, and this
   keyframe reads it. One number, one source, nothing to drift. */
@keyframes spf-ring-fill { from { stroke-dashoffset: var(--spf-ring-c); } }
.spf-ring svg [data-role="ring-arc"] { animation: spf-ring-fill 520ms ease-out; transition: stroke-dashoffset 520ms ease-out; }
.spf-btn, .spf-seg-opt, button.spf-row { transition: opacity 80ms ease-out, background-color 200ms ease-out; }
@media (prefers-reduced-motion: reduce) {
  .spf-skel-bar { animation: none; }
  .spf-sheet-panel, .spf-ring svg [data-role="ring-arc"] { animation: none; }
  .spf-ring svg [data-role="ring-arc"], .spf-btn, .spf-seg-opt, button.spf-row { transition: none; }
}
