/* ══════════════════════════════════════════════════════════════════════════
   ui-components.css — the card and type layer, for EVERY page.

   Why it is not in app-shell.css
   ─────────────────────────────
   That file is the navigation rail, the drawer and the app header. The public
   pages — pricing, docs, methodology, the samples, privacy, terms — have no
   rail and must not grow one: they are read by people who are not signed in,
   and an application chrome around a privacy policy is wrong. What they DO
   share with the app is the card, the tag, the tile and the type scale, and
   until now they each drew their own: six card-ish rules on /pricing, two on
   /docs, two on /preview, and one shadow-and-radius pair per sample page, all
   slightly different. Splitting the layer out is what lets them share the
   half that should be shared and skip the half that should not.

   Loaded by all pages; app-shell.css is loaded only by the two that have a rail.
   ══════════════════════════════════════════════════════════════════════════ */

/* design-tokens.css is 312 variables and a reset with no components, so every
   page rebuilt its own cards, tags and grids and they drifted. This is that
   layer, built to the approved v2 design.

   One rule governs every number that appears here: if Polaris does not
   MEASURE it, it does not get drawn. The reference design shows a 68% ring,
   a milestone checklist and "2h ago" activity; those are prototype fixtures.
   What this product actually holds is node_count on every plan version
   (150/150 rows in production) and the node set its mode licenses — so the
   ring is nodes produced over nodes expected, and the checklist is the node
   list. readiness_score exists but is present on only 44 of 150 versions and
   null on the newest, so it is shown as a figure when there IS one and never
   as a ring that would read as zero.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Card ──────────────────────────────────────────────────────────────── */
.pol-card{
  background:var(--panel); border:1px solid var(--line-soft); border-radius:1.125rem;
  padding:1.375rem; box-shadow:var(--shadow, 0 5px 22px rgba(35,48,74,.04));
}
.pol-card-head{ display:flex; align-items:center; gap:0.625rem; margin-bottom:1rem; }
.pol-card-head h3{ margin:0; font-size:var(--fs-md); font-weight:700; }
.pol-tile{
  display:grid; place-items:center; flex:none; width:35px; height:35px;
  border-radius:0.5625rem; background:var(--c-accent-soft); color:var(--c-accent);
}

/* ── Tag ───────────────────────────────────────────────────────────────── */
.pol-tag{
  display:inline-flex; align-items:center; border-radius:999px;
  padding:0.25rem 0.5625rem; font-size:var(--fs-micro); font-weight:700;
  white-space:nowrap;
}
.pol-tag.ok{   background:var(--st-ok-bg);   color:var(--st-ok-fg); }
.pol-tag.warn{ background:var(--st-warn-bg); color:var(--st-warn-fg); }
.pol-tag.info{ background:var(--st-hypo-bg); color:var(--st-hypo-deep); }
.pol-tag.idle{ background:var(--panel-2);    color:var(--ink-3); }

/* ── Ring ──────────────────────────────────────────────────────────────── */
/* role="img" with an aria-label in the markup: the percentage is drawn as a
   stroke, and a stroke has no text for a screen reader. */
.pol-ring{ position:relative; width:105px; height:105px; flex:none; }
.pol-ring svg{ width:100%; height:100%; transform:rotate(-90deg); }
.pol-ring span{
  position:absolute; inset:0; display:grid; place-items:center;
  font-size:var(--fs-xl); font-weight:700;
}

/* ── The command panel ─────────────────────────────────────────────────── */
/* Deep like the rail, and for the same reason: it is the fixed thing the page
   is arranged around. It uses the rail tokens so a white-label palette moves
   the two together instead of leaving one behind. */
.pol-command{
  position:relative; isolation:isolate; overflow:hidden;
  border-radius:1.25rem; padding:1.75rem;
  background:
    radial-gradient(ellipse at 60% 0%, color-mix(in srgb, var(--c-accent) 22%, var(--shell-rail-2)) 0%, transparent 62%),
    linear-gradient(140deg, var(--shell-rail-2), var(--shell-rail));
  color:var(--shell-rail-ink);
  box-shadow:0 12px 34px rgba(23,34,55,.14);
}
.pol-command:before{
  content:''; position:absolute; inset:0; z-index:-2; opacity:.28;
  background-image:radial-gradient(var(--shell-rail-ink-2) 1px, transparent 1px);
  background-size:67px 53px;
}
.pol-orbits{ position:absolute; inset:0; width:100%; height:100%; z-index:-1; pointer-events:none; }
.pol-command-head{ display:flex; justify-content:space-between; gap:1.5rem; align-items:flex-start; margin-bottom:1.75rem; }
.pol-command-head h2{
  margin:0; font-family:var(--font-display, Georgia, serif); font-weight:400;
  font-size:var(--fs-2xl); line-height:1.15; letter-spacing:-.02em; max-width:22ch;
}
/* Persian has no serif display face here and joins its letters, so the serif
   swap and the tightened tracking both have to come off. */
:where([lang="fa"], [dir="rtl"]) .pol-command-head h2{ font-family:var(--font-fa); letter-spacing:normal; }
.pol-command-head p{ margin:0.5rem 0 0; font-size:var(--fs-xs); color:var(--shell-rail-ink-2); }
.pol-command-grid{ display:grid; grid-template-columns:.85fr 1.12fr 1fr; gap:1.125rem; align-items:stretch; }

.pol-glass{
  border:1px solid color-mix(in srgb, var(--shell-rail-ink) 22%, transparent);
  background:linear-gradient(120deg,
    color-mix(in srgb, var(--shell-rail-ink) 14%, transparent),
    color-mix(in srgb, var(--shell-rail-ink) 6%, transparent));
  backdrop-filter:blur(9px);
  border-radius:1rem; padding:1.25rem;
  box-shadow:0 9px 30px rgba(9,15,25,.13);
}
.pol-glass h3{ margin:0 0 0.3125rem; font-size:var(--fs-md); font-weight:700; }
.pol-glass p, .pol-glass small{ color:var(--shell-rail-ink-2); }
.pol-glass.feature{
  padding:1.375rem;
  border-color:color-mix(in srgb, var(--shell-rail-ink) 32%, transparent);
  box-shadow:0 0 0 5px color-mix(in srgb, var(--c-accent) 8%, transparent), 0 12px 24px rgba(6,11,24,.15);
}
.pol-eyebrow{
  display:flex; align-items:center; gap:0.375rem;
  font-size:var(--fs-micro); font-weight:700; letter-spacing:var(--tracking-label);
  text-transform:uppercase; color:var(--shell-rail-ink-2);
}
.pol-glass.feature h3{ font-size:var(--fs-xl); font-weight:600; margin:0.5rem 0 0.1875rem; }
.pol-progress{ display:flex; align-items:center; gap:1.125rem; margin:1.375rem 0; }
.pol-steps{ list-style:none; padding:0; margin:0; display:grid; gap:0.5rem; font-size:var(--fs-micro); }
.pol-steps li{ display:flex; gap:0.5rem; align-items:center; color:var(--shell-rail-ink); }
.pol-steps li.todo{ color:var(--shell-rail-ink-2); }

.pol-avatars{ display:flex; align-items:center; margin:1rem 0 0.75rem; }
.pol-avatars .shell-avatar{ width:42px; height:42px; margin-inline-end:-8px; border:2px solid var(--shell-rail); }
.pol-roles{ display:flex; flex-wrap:wrap; gap:0.3125rem; margin-bottom:0.75rem; }
.pol-role{
  font-size:var(--fs-micro); padding:0.25rem 0.5rem; border-radius:999px;
  border:1px solid color-mix(in srgb, var(--shell-rail-ink) 24%, transparent);
  color:var(--shell-rail-ink-2);
}

.pol-row{
  display:flex; align-items:center; gap:0.625rem; width:100%;
  padding:0.875rem 0; background:transparent; color:inherit; font:inherit;
  text-align:start; border:0;
  border-top:1px solid color-mix(in srgb, var(--shell-rail-ink) 14%, transparent);
  cursor:pointer;
}
.pol-row:first-of-type{ border-top:0; }
.pol-row > span:first-child{ flex:1; min-width:0; }
.pol-row strong{ display:block; font-size:var(--fs-xs); font-weight:600; }
.pol-row small{ display:block; font-size:var(--fs-micro); margin-top:0.25rem; color:var(--shell-rail-ink-2); }
.pol-panel-head{ display:flex; align-items:center; justify-content:space-between; gap:0.75rem; margin-bottom:0.75rem; }

/* Buttons inside the command panel sit on a DARK ground, and the page's own
   .btn-ghost / .btn-primary are drawn for a light one — a ghost button there
   renders as a pale filled box with invisible text. Scoped overrides rather
   than new classes, so the markup keeps using the buttons the rest of the page
   uses and nothing has to remember a second vocabulary. */
.pol-command .btn-ghost{
  background:transparent; border-color:color-mix(in srgb, var(--shell-rail-ink) 30%, transparent);
  color:var(--shell-rail-ink);
}
.pol-command .btn-ghost:hover{ background:color-mix(in srgb, var(--shell-rail-ink) 10%, transparent); }
.pol-command .btn-primary{ background:var(--c-accent); color:var(--c-on-accent); border-color:transparent; }
.pol-command .btn-primary:hover{ background:var(--c-accent-deep); }
.pol-command a{ color:var(--shell-rail-ink); }

/* ── Insight strip ─────────────────────────────────────────────────────── */
.pol-insights{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:1.125rem; margin:1.375rem 0; }
.pol-insight-body{ font-size:var(--fs-sm); color:var(--ink-3); }
.pol-insight-body p{ margin:0 0 1rem; }
.pol-activity{ display:flex; gap:0.625rem; align-items:flex-start; margin-top:0.875rem; }
.pol-activity div{ flex:1; min-width:0; }
.pol-activity strong{ display:block; font-size:var(--fs-xs); }
.pol-activity small{ display:block; font-size:var(--fs-micro); color:var(--ink-3); margin-top:0.1875rem; }
.pol-activity time{ font-size:var(--fs-micro); color:var(--ink-3); white-space:nowrap; }

/* ── Plan rows ─────────────────────────────────────────────────────────── */
.pol-list{ display:grid; gap:0.875rem; }
.pol-plan{ display:flex; align-items:center; gap:1.25rem; }
.pol-plan .pol-plan-desc{ flex:1; min-width:0; }
.pol-plan h3{ margin:0; font-size:var(--fs-lg); font-weight:700; }
.pol-plan p{ margin:0.3125rem 0 0; font-size:var(--fs-sm); color:var(--ink-3); }

/* ── Empty ─────────────────────────────────────────────────────────────── */
.pol-empty{
  grid-column:1/-1; padding:2.5rem; text-align:center; color:var(--ink-3);
  border:1px dashed var(--line); border-radius:0.9375rem;
}
.pol-empty p{ margin:0.625rem 0 1.25rem; }

@media (max-width:1200px){
  .pol-command{ padding:1.375rem; }
  .pol-command-grid{ gap:0.75rem; }
  .pol-glass{ padding:1rem; }
  .pol-ring{ width:80px; height:80px; }
  .pol-insights{ gap:0.75rem; }
  .pol-card{ padding:1.125rem; }
}
@media (max-width:1000px){
  .pol-command-grid{ grid-template-columns:1fr 1.3fr; }
  .pol-command-grid > :last-child{ grid-column:1/-1; }
  .pol-insights{ grid-template-columns:1fr 1fr; }
  .pol-insights > :last-child{ grid-column:1/-1; }
}
@media (max-width:760px){
  .pol-command-grid{ grid-template-columns:1fr; }
  .pol-command-grid > :last-child{ grid-column:auto; }
  /* What you are working on comes first on a phone. */
  .pol-command-grid .feature{ order:-1; }
  .pol-insights{ grid-template-columns:1fr; }
  .pol-insights > :last-child{ grid-column:auto; }
  .pol-plan{ flex-wrap:wrap; }
  .pol-plan .pol-plan-desc{ min-width:180px; }
  .pol-command-head h2{ font-size:var(--fs-xl); }
}

/* ── Toolbar: filter chips + search ────────────────────────────────────── */
/* The counts on the chips are not decoration — with 83 assets on one brand,
   a filter that might match nothing is a click the reader should not have to
   spend. Each chip says how many it would leave. */
.pol-toolbar{ display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap; margin:0 0 1.125rem; }
.pol-toolbar-gap{ flex:1; }
.pol-chips{ display:flex; gap:0.25rem; flex-wrap:wrap; }
.pol-chip{
  display:inline-flex; align-items:center; gap:0.375rem; min-height:44px;
  padding:0.5rem 0.875rem; border:1px solid transparent; border-radius:0.5625rem;
  background:transparent; color:var(--ink-3); font:inherit; font-size:var(--fs-sm);
  cursor:pointer;
}
.pol-chip:hover{ background:var(--panel-2); color:var(--ink); }
.pol-chip.on{ background:var(--shell-rail); color:var(--shell-rail-ink); }
.pol-chip-n{
  font-size:var(--fs-micro); font-weight:700; opacity:.7;
  padding-inline-start:0.125rem;
}
.pol-search{
  display:flex; align-items:center; gap:0.5rem; min-height:44px;
  padding:0 0.75rem; border:1px solid var(--line); border-radius:0.625rem;
  background:var(--panel); color:var(--ink-3);
}
.pol-search:focus-within{ outline:2px solid var(--c-accent); outline-offset:1px; }
.pol-search input{
  width:12rem; min-width:0; border:0; background:transparent; color:var(--ink);
  font:inherit; font-size:var(--fs-sm); outline:none;
}
@media (max-width:760px){
  .pol-toolbar-gap{ display:none; }
  .pol-search{ width:100%; }
  .pol-search input{ width:100%; }
}

/* ── Team members ──────────────────────────────────────────────────────── */
.tp-members{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:1rem; margin:0.75rem 0; }
.tp-member{ display:flex; flex-direction:column; align-items:flex-start; gap:0.5rem; padding:1.125rem; }
.tp-member .shell-avatar{ width:48px; height:48px; font-size:var(--fs-md); margin-bottom:0.25rem; }
.tp-member .tp-who{ font-size:var(--fs-sm); font-weight:600; overflow-wrap:anywhere; }
.tp-member select{ font-size:var(--fs-micro); max-width:100%; }
@media (max-width:1000px){ .tp-members{ grid-template-columns:1fr 1fr; } }
@media (max-width:760px){ .tp-members{ grid-template-columns:1fr; } }

/* ══════════════════════════════════════════════════════════════════════════
   v3 — the focus panel, the phase track and the review queue
   ─────────────────────────────────────────────────────────────────────────
   The approved v3 reference replaces the v2 progress RING with a five-phase
   track, moves the team inside the focus panel, and adds a "needs your
   review" queue. Two of those changes are honesty improvements, not just
   visual ones:

   · The ring said "7/8 nodes produced", which is true and unreadable — it
     asks the reader to know what a node is. The five phases are the same
     eight nodes grouped the way the work is actually sequenced (Research,
     Strategy, Creative, Production, Launch), so the same fact reads as
     progress instead of trivia. It is still counted from real outputs; a
     phase is done when its nodes have produced, never on a timer.
   · The review queue is the ONE thing on this page that is genuinely
     addressed to the reader. Polaris already knows it — the governance
     workflows this person is a participant on — and it was buried in a
     table three routes away.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Breadcrumb + welcome row ──────────────────────────────────────────── */
.pol-crumb{
  display:flex; align-items:center; gap:0.5rem; flex-wrap:wrap;
  font-size:var(--fs-xs); color:var(--ink-3); margin-bottom:0.75rem;
}
.pol-crumb a{ color:var(--ink-3); text-decoration:none; }
.pol-crumb a:hover{ color:var(--ink); text-decoration:underline; }
.pol-welcome{ display:flex; align-items:flex-end; gap:1rem; flex-wrap:wrap; margin-bottom:1.25rem; }
.pol-welcome-text{ flex:1; min-width:14rem; }
.pol-welcome .pol-date{
  font-size:var(--fs-micro); font-weight:700; letter-spacing:var(--tracking-label);
  text-transform:uppercase; color:var(--ink-3); margin:0 0 0.375rem;
}
.pol-welcome h2{ margin:0; font-size:var(--fs-2xl); font-weight:700; letter-spacing:-.02em; }
.pol-welcome p{ margin:0.375rem 0 0; font-size:var(--fs-sm); color:var(--ink-3); }

/* ── The focus panel ───────────────────────────────────────────────────── */
.pol-focus{ display:grid; grid-template-columns:minmax(0,1.55fr) minmax(0,1fr); gap:1.125rem; align-items:stretch; }
.pol-focus-main{ display:flex; flex-direction:column; justify-content:space-between; gap:1.25rem; }
.pol-focus h3{ margin:0.5rem 0 0.25rem; font-size:var(--fs-2xl); font-weight:700; letter-spacing:-.02em; }
.pol-focus-sub{ font-size:var(--fs-sm); color:var(--shell-rail-ink-2); }

/* ── Phase track ───────────────────────────────────────────────────────── */
.pol-phases{ display:flex; align-items:flex-start; gap:0.25rem; margin:1.25rem 0 1rem; }
.pol-phase{ flex:1; min-width:0; display:flex; flex-direction:column; align-items:center; gap:0.4375rem; text-align:center; }
.pol-phase-dot{
  width:30px; height:30px; flex:none; display:grid; place-items:center;
  border-radius:50%; font-size:var(--fs-xs); font-weight:700;
  border:1px solid color-mix(in srgb, var(--shell-rail-ink) 28%, transparent);
  color:var(--shell-rail-ink-2); background:transparent;
}
.pol-phase.done .pol-phase-dot{ background:var(--c-accent); color:var(--c-on-accent); border-color:transparent; }
.pol-phase.now  .pol-phase-dot{ border-color:var(--c-accent); color:var(--shell-rail-ink); box-shadow:0 0 0 3px var(--c-accent-soft); }
.pol-phase-name{ font-size:var(--fs-micro); color:var(--shell-rail-ink-2); overflow-wrap:anywhere; }
.pol-phase.done .pol-phase-name, .pol-phase.now .pol-phase-name{ color:var(--shell-rail-ink); }
/* The rule between the dots reads as a track, and it must flip with the text. */
.pol-phase + .pol-phase{ position:relative; }
.pol-phase + .pol-phase::before{
  content:''; position:absolute; inset-block-start:15px; inset-inline-end:50%; width:100%;
  border-top:1px solid color-mix(in srgb, var(--shell-rail-ink) 22%, transparent); z-index:0;
}
.pol-phase.done::before{ border-color:var(--c-accent); }
.pol-phase-dot{ position:relative; z-index:1; }

/* ── Numbered plan stack ───────────────────────────────────────────────── */
.pol-stack{ display:grid; gap:0.625rem; }
/* ⚠️ NOT .pol-tile — that name was already taken by the 35px icon tile in the
   card head above, and a second definition would have silently turned every
   icon in the product into a full-width row. Measured: 26 elements matched
   the shared name. */
.pol-row-tile{
  display:flex; align-items:center; gap:0.75rem; width:100%; padding:0.75rem;
  border:1px solid var(--line-soft); border-radius:0.875rem; background:var(--panel);
  color:var(--ink); font:inherit; text-align:start; cursor:pointer; min-height:44px;
}
.pol-row-tile:hover{ background:var(--st-paper); }
.pol-row-tile[aria-current]{ border-color:var(--c-accent); background:var(--c-accent-soft); }
.pol-row-n{
  flex:none; font-size:var(--fs-xs); font-weight:700; color:var(--ink-3);
  font-variant-numeric:tabular-nums; min-width:1.5rem;
}
.pol-row-body{ flex:1; min-width:0; }
.pol-row-body strong{ display:block; font-size:var(--fs-sm); overflow-wrap:anywhere; }
.pol-row-body small{ display:block; font-size:var(--fs-micro); color:var(--ink-3); margin-top:0.125rem; }

/* ── Screen-reader-only ────────────────────────────────────────────────────
   The v3 reference relies on .sr-only and Polaris never defined it, so every
   "Research — produced" hint written for a screen reader rendered on screen
   under its own phase label. */
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}

/* ── Review queue ──────────────────────────────────────────────────────── */
.pol-review{ display:grid; gap:0.625rem; }
.pol-review-row{
  display:flex; align-items:center; gap:0.75rem; padding:0.625rem 0;
  border-top:1px solid var(--line-soft);
}
.pol-review-row:first-child{ border-top:0; }
.pol-review-row > div{ flex:1; min-width:0; }
.pol-review-row strong{ display:block; font-size:var(--fs-sm); overflow-wrap:anywhere; }
.pol-review-row small{ display:block; font-size:var(--fs-micro); color:var(--ink-3); margin-top:0.125rem; }

@media (max-width:1000px){ .pol-focus{ grid-template-columns:1fr; } }
@media (max-width:760px){
  .pol-phases{ flex-wrap:wrap; gap:0.75rem 0.25rem; }
  .pol-phase{ flex:1 1 30%; }
  .pol-phase + .pol-phase::before{ display:none; }
  .pol-welcome h2{ font-size:var(--fs-xl); }
}

/* ── White-label preview ───────────────────────────────────────────────── */
/* The panel used to be four inputs and a file picker: you could not see what
   you were making until you exported a document. This is the cover strip the
   client actually receives, built from the same three values the exporter
   reads — so an empty field shows as empty rather than as a placeholder that
   flatters. */
.wl-preview{
  border:1px solid var(--line-soft); border-radius:0.875rem; overflow:hidden;
  background:var(--panel-2); margin-bottom:1.125rem;
}
.wl-strip{ display:flex; align-items:center; gap:0.75rem; padding:1rem 1.125rem; }
.wl-logo{
  display:grid; place-items:center; width:40px; height:40px; flex:none;
  border-radius:0.5rem; border:1px dashed var(--line); color:var(--ink-3); overflow:hidden;
}
.wl-logo img{ max-width:100%; max-height:100%; object-fit:contain; }
.wl-names{ min-width:0; }
.wl-names b{ display:block; font-size:var(--fs-md); overflow-wrap:anywhere; }
.wl-names small{ display:block; font-size:var(--fs-xs); color:var(--ink-3); margin-top:0.125rem; overflow-wrap:anywhere; }
.wl-rule{ height:4px; background:var(--c-accent); }
.wl-caption{ padding:0.75rem 1.125rem; font-size:var(--fs-micro); color:var(--ink-3); }

.wl-grid{ display:grid; grid-template-columns:1fr auto; gap:0.75rem; margin-bottom:1rem; }
.wl-field{ display:grid; gap:0.3125rem; font-size:var(--fs-xs); color:var(--ink-3); min-width:0; }
.wl-field.wl-wide{ grid-column:1/-1; }
.wl-field input{
  width:100%; min-height:44px; padding:0.5rem 0.75rem; font:inherit; font-size:var(--fs-sm);
  border:1px solid var(--line); border-radius:0.625rem; background:var(--c-field); color:var(--c-on-field);
}
.wl-field input[type="color"]{ width:56px; padding:0.25rem; cursor:pointer; }
.wl-actions{ display:flex; align-items:center; gap:0.625rem; flex-wrap:wrap; }
@media (max-width:760px){ .wl-grid{ grid-template-columns:1fr; } .wl-field.wl-wide{ grid-column:auto; } }

/* ── Brand essentials, in the studio ───────────────────────────────────── */
.wl-kit{ margin-bottom:1.125rem; }
.wl-kit-row{ display:flex; align-items:center; gap:0.75rem; margin-bottom:0.875rem; }
.wl-swatches{ display:flex; gap:0.5rem; margin:0 0 0.625rem; }
.wl-swatches span{ flex:1; height:28px; border-radius:0.4375rem; border:1px solid var(--line-soft); }
