/* ============================================================
   Pagoda Web Co — Client Portal design system v2
   From Nate's locked UI mockups (Aug 2026):
   pine/cream/clay/glow · Newsreader + Karla + Roboto Mono ·
   soft radii (shell 16 / cards 14 / pills 999) · easing
   cubic-bezier(.22,1,.36,1) · reduced-motion safe.
   ============================================================ */

:root {
  --pine: #1F3D34;
  --pine-2: #2A5245;        /* pine hover */
  --clay: #C75B39;
  /* Clay for any surface that carries white text. --clay itself is 4.2:1
     against white, under the 4.5:1 WCAG AA floor for body-size text; this
     shade is 4.8:1 and reads as the same color. Use --clay for accents,
     borders and fills with no text on them. */
  --clay-fill: #BA5231;
  --clay-dark: #833E1E;
  --glow: #E0A34E;
  --glow-ink: #75590F;      /* AA text on glow tints */
  --cream: #F7F1E6;
  --card: #FFFDF8;
  --line: #E5DBC8;
  --line-strong: #C9BFAC;
  --ink: #23201C;
  --muted: #5C665F;
  --link: #A85028;
  --ok: #2E6B4F;
  --danger: #A8302B;        /* error / destructive ink */
  --warn: #8A5A1A;          /* caution ink */
  --surface-sunken: #F1EADB;
  --on-fill: #fff;          /* text/fill on solid colored surfaces */
  --input-border: #8F8574;  /* 3:1 on --card */

  /* Type scale. Nothing user-facing goes below --fs-xs. */
  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-base: 15px;
  --fs-md: 16px;
  --fs-lg: 18px;
  --fs-xl: 24px;
  --fs-2xl: 32px;

  --r-shell: 16px;
  --r-card: 14px;
  --r-input: 10px;
  --r-bubble: 12px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  --display: 'Newsreader', Georgia, serif;
  --font: 'Karla', -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: 'Roboto Mono', ui-monospace, Menlo, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

body { min-height: 100vh; display: flex; flex-direction: column; }

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.12;
  margin: 0 0 var(--space-3);
  color: var(--ink);
}

h1 { font-size: 1.9rem; font-weight: 500; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.2rem; }

p { line-height: 1.55; margin: 0 0 var(--space-3); }

a { color: var(--link); }
a:hover { color: var(--clay-dark); }

em.accent, .accent-word { font-style: italic; color: var(--clay); }

/* Micro-label: the mono eyebrow used everywhere */
.micro {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.num, .stat-number, .progress-pct { font-variant-numeric: tabular-nums; }

/* ---------- Motion ---------- */

@keyframes fadeUp   { from { opacity: 0; transform: translateY(12px); }  to { opacity: 1; transform: none; } }
@keyframes heroDown { from { opacity: 0; transform: translateY(-18px); } to { opacity: 1; transform: none; } }
@keyframes rowIn    { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }
@keyframes popIn    { from { opacity: 0; transform: scale(0); }          to { opacity: 1; transform: scale(1); } }
@keyframes fillBar  { from { width: 0; } }
@keyframes pulseRing {
  0%   { box-shadow: 0 0 0 0 rgba(224,163,78,.45); }
  70%  { box-shadow: 0 0 0 10px rgba(224,163,78,0); }
  100% { box-shadow: 0 0 0 0 rgba(224,163,78,0); }
}

.anim-hero   { animation: heroDown .7s var(--ease) backwards; }
.anim-up     { animation: fadeUp .6s var(--ease) backwards; }
.anim-up-1   { animation: fadeUp .6s var(--ease) .1s backwards; }
.anim-up-2   { animation: fadeUp .7s var(--ease) .18s backwards; }
.anim-up-3   { animation: fadeUp .6s var(--ease) .3s backwards; }
.anim-up-4   { animation: fadeUp .6s var(--ease) .45s backwards; }
.anim-up-5   { animation: fadeUp .6s var(--ease) .55s backwards; }
.anim-up-6   { animation: fadeUp .6s var(--ease) .65s backwards; }
.anim-row-1  { animation: rowIn .5s var(--ease) .38s backwards; }
.anim-row-2  { animation: rowIn .5s var(--ease) .46s backwards; }
.anim-row-3  { animation: rowIn .5s var(--ease) .54s backwards; }
.anim-row-4  { animation: rowIn .5s var(--ease) .62s backwards; }
.anim-row-5  { animation: rowIn .5s var(--ease) .70s backwards; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- Focus ---------- */

a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: 2px;
}

/* On pine the clay ring is too dark to see; use glow. */
.pine-hero a:focus-visible, .pine-hero button:focus-visible,
.pine-hero input:focus-visible, .pine-hero select:focus-visible,
.pine-hero textarea:focus-visible, .pine-hero [tabindex]:focus-visible,
body.auth-body .auth-footnote a:focus-visible {
  outline-color: var(--glow);
}

/* ---------- Admin "view as client" preview banner ---------- */
/* In normal document flow (not fixed) -- #site-header isn't sticky
   either, so there's no overlap risk to guard against. Sits above
   .pine-hero, same full-bleed treatment. */

.admin-preview-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  background: var(--glow);
  color: var(--pine);
  font-family: var(--font);
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
}

.admin-preview-banner a {
  color: var(--pine);
  text-decoration: underline;
}

.admin-preview-banner a:hover { color: var(--ink); }

/* ---------- Pine hero shell (header + page hero live inside) ---------- */

.pine-hero { background: var(--pine); color: var(--cream); }

#site-header { background: transparent; }

.site-header__inner {
  max-width: 1080px;
  margin: 0 auto;
  padding: var(--space-4) var(--space-6);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  border-bottom: 1px solid rgba(247,241,230,.14);
}

.wordmark { display: flex; align-items: baseline; gap: 8px; margin-right: auto; text-decoration: none; }
.wordmark-serif { font-family: var(--display); font-size: 21px; font-weight: 500; color: var(--cream); }
.wordmark-mono  { font-family: var(--mono); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .3em; color: var(--glow); }

.site-nav {
  display: flex;
  gap: 6px;
  align-items: center;
  background: rgba(247,241,230,.08);
  border: 1px solid rgba(247,241,230,.14);
  border-radius: 999px;
  padding: 5px;
  order: 3;
  width: 100%;
  flex-wrap: wrap;            /* phones/tablets: pills wrap onto 2 rows, no hidden sideways scroll */
  justify-content: center;
}

@media (max-width: 859px) {
  .site-nav { border-radius: var(--r-card); }
  .site-nav a { flex: 1 1 auto; justify-content: center; padding: 8px 14px; }
}

.site-nav a {
  color: rgba(247,241,230,.7);
  text-decoration: none;
  font-size: 13.5px;
  font-weight: 600;
  padding: 8px 18px;
  border-radius: 999px;
  white-space: nowrap;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  transition: background .2s, color .2s;
}

.site-nav a:hover { background: rgba(247,241,230,.12); color: var(--cream); }
.site-nav a[aria-current="page"] { background: var(--cream); color: var(--pine); }
.site-nav a.nav-admin[aria-current="page"] { background: var(--glow); color: var(--pine); }

.btn-signout {
  order: 2;
  background: transparent;
  color: rgba(247,241,230,.75);
  border: 1px solid rgba(247,241,230,.3);
  border-radius: 999px;
  padding: 9px 18px;
  font-family: var(--font);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  min-height: 44px;
  transition: border-color .2s, color .2s;
}

.btn-signout:hover { border-color: var(--cream); color: var(--cream); }

@media (min-width: 860px) {
  .site-nav { order: 2; width: auto; flex-wrap: nowrap; }
  .btn-signout { order: 3; }
}

/* Page hero (inside .pine-hero, below the header bar) */
.hero-content {
  max-width: 1080px;
  margin: 0 auto;
  padding: var(--space-6) var(--space-6) var(--space-5);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-5);
  width: 100%;
}

.hero-eyebrow {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--glow);
}

.hero-title {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.9rem, 4vw, 2.15rem);
  letter-spacing: -0.01em;
  line-height: 1.08;
  color: var(--cream);
  margin: 8px 0 0;
}

.hero-title em, .hero-title .accent-word { font-style: italic; color: var(--glow); }

.hero-sub { font-size: 13.5px; color: rgba(247,241,230,.7); }

/* Right side of the hero on admin-client.html: stage/plan/contact text
   stacked above the "View as client" preview link (see hero-content's
   space-between layout -- this is its 2nd flex child). */
.hero-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.hero-side .hero-sub { text-align: right; }

.hero-view-as {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--glow);
  text-decoration: none;
  padding: 6px 12px;
  border: 1px solid var(--glow);
  border-radius: 6px;
  white-space: nowrap;
}
.hero-view-as:hover { background: var(--glow); color: var(--glow-ink); }

/* Dashboard greeting variant — larger, with attention rows in-hero */
.hero-greeting {
  font-size: clamp(1.9rem, 4.5vw, 2.75rem);
}

.attention-block { margin-top: var(--space-5); max-width: 720px; width: 100%; }
.attention-heading {
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: rgba(247,241,230,.55);
  margin-bottom: 4px;
}

.attention-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 13px 0;
  border-bottom: 1px solid rgba(247,241,230,.15);
  color: var(--cream);
  text-decoration: none;
  font-size: var(--fs-base);
  min-height: 44px;
  transition: transform .25s var(--ease);
}

.attention-row:last-child { border-bottom: none; }
.attention-row:hover { transform: translateX(6px); color: var(--cream); }
.attention-arrow { color: var(--glow); flex: none; }
.attention-secondary { color: rgba(247,241,230,.6); font-size: 12.5px; font-weight: 400; }

/* ---------- Main column ---------- */

main {
  flex: 1;
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  padding: var(--space-5) var(--space-6) var(--space-7);
}

.page-title { margin-bottom: var(--space-5); }
.page-title p { color: var(--muted); margin-bottom: 0; }

/* ---------- Cards ---------- */

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 26px 28px;
  margin-bottom: var(--space-4);
  transition: transform .25s var(--ease), box-shadow .25s;
}

.card-hover:hover, .link-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 28px rgba(35,32,28,.09);
}

.card h2, .card h3 { font-family: var(--display); }

.card-row { display: flex; flex-wrap: wrap; gap: var(--space-4); }

.link-card {
  display: block;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: var(--space-4) 20px;
  text-decoration: none;
  color: var(--ink);
  flex: 1 1 200px;
  transition: transform .25s var(--ease), box-shadow .25s, border-color .2s;
}

.link-card h3 { color: var(--link); margin-bottom: var(--space-1); font-size: 1.15rem; }
.link-card p { margin: 0; color: var(--muted); font-size: 0.85rem; }
.link-card:hover { color: var(--ink); }

.empty-state {
  background: var(--card);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-card);
  padding: var(--space-6);
  text-align: center;
  color: var(--muted);
}

.empty-state .micro { display: block; margin-top: 6px; }

.banner {
  background: rgba(224,163,78,.12);
  border: 1px solid var(--glow);
  border-radius: var(--r-card);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-5) auto 0;
  max-width: 1080px;
  font-size: 0.88rem;
  color: var(--glow-ink);
}

.banner-wrap { padding: 0 var(--space-6); }

/* ---------- Forms ---------- */

label {
  display: block;
  font-family: var(--font);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
  margin-bottom: 6px;
}

input[type="text"], input[type="email"], input[type="password"],
input[type="url"], input[type="date"], input[type="tel"], input[type="number"], input[type="search"], select, textarea {
  width: 100%;
  font-family: var(--font);
  font-size: 14px;
  padding: 11px 14px;
  min-height: 44px;
  border: 1px solid var(--input-border);
  border-radius: var(--r-input);
  background: var(--card);
  color: var(--ink);
  transition: border-color .2s;
}

input:focus, select:focus, textarea:focus { border-color: var(--pine); }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: 1px;
  border-color: var(--pine);
}
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--danger); }

/* iOS Safari zooms any field under 16px on focus. */
@media (max-width: 640px) {
  input, select, textarea { font-size: var(--fs-md) !important; }
}

/* A checkbox + its own sentence of label text (e.g. an agreement
   acknowledgment) — overrides the default uppercase/mono label style,
   which is meant for form field captions, not readable prose. */
.field-check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-family: var(--font);
  font-size: 14.5px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
  margin-bottom: 0;
  cursor: pointer;
}
.field-check input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin-top: 2px;
  flex: none;
  accent-color: var(--pine);
}

input[type="file"] { border: none; background: none; padding: 6px 0; min-height: 0; }

textarea { min-height: 110px; resize: vertical; border-radius: var(--r-bubble); }

.field { margin-bottom: var(--space-4); }
.field-hint { color: var(--muted); font-size: 0.8rem; margin-top: var(--space-1); font-family: var(--font); text-transform: none; letter-spacing: 0; }

fieldset { border: 1px solid var(--line); border-radius: var(--r-bubble); padding: var(--space-4); margin: 0 0 var(--space-4); }
legend {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--pine);
  padding: 0 var(--space-2);
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 11px 24px;
  border: none;
  border-radius: 999px;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  background: var(--clay-fill);
  color: var(--on-fill);
  transition: background .2s, transform .2s;
}

.btn:hover { background: var(--clay-dark); color: var(--on-fill); transform: translateY(-1px); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }

.btn-secondary {
  background: transparent;
  color: var(--pine);
  border: 1px solid var(--pine);
}

.btn-secondary:hover { background: var(--pine); color: var(--cream); transform: none; }

.btn-pine { background: var(--pine); color: var(--cream); }
.btn-pine:hover { background: var(--pine-2); color: var(--cream); }

.btn-ghost {
  background: none;
  border: none;
  color: var(--link);
  font-weight: 600;
  border-radius: 999px;
  padding: 10px 14px;
  transition: background .2s;
}

.btn-ghost:hover { background: rgba(168,80,40,.08); transform: none; color: var(--link); }
.btn-ghost:disabled { color: var(--line-strong); }

.btn-block { width: 100%; }
.btn-sm { min-height: 38px; padding: 8px 16px; font-size: 12.5px; }

/* ---------- Chips (status pills) ---------- */

.chip {
  display: inline-block;
  font-family: var(--mono);
  text-transform: uppercase;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid currentColor;
  white-space: nowrap;
}

.chip-new         { color: var(--clay-dark); border-color: var(--clay); background: rgba(199,91,57,.08); }
.chip-in_progress { color: var(--glow-ink); border-color: var(--glow); background: rgba(224,163,78,.12); }
.chip-done        { color: var(--ok); border-color: var(--ok); background: rgba(46,107,79,.08); }
.chip-wont_do     { color: var(--muted); border-color: var(--line-strong); background: none; }
.chip-kind        { color: var(--muted); border-color: var(--line-strong); background: none; }
.chip-ext         { color: var(--muted); border-color: var(--line-strong); min-width: 44px; text-align: center; }
.chip-required    { color: var(--clay-dark); border-color: var(--clay); background: rgba(199,91,57,.08); }

/* ---------- Timeline ---------- */

.timeline { display: flex; flex-direction: column; gap: var(--space-3); list-style: none; margin: 0; padding: 0; }
.timeline-step { display: flex; align-items: center; gap: var(--space-3); }

.timeline-dot {
  flex: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 2px solid var(--line);
  background: var(--on-fill);
}

.timeline-step.is-done .timeline-dot    { background: var(--pine); border-color: var(--pine); }
.timeline-step.is-current .timeline-dot {
  background: var(--glow); border-color: var(--glow);
  animation: pulseRing 2.4s ease-out 1.8s infinite;
}
.timeline-step.is-current .timeline-label { color: var(--ink); font-weight: 700; }
.timeline-step.is-done .timeline-label { color: var(--ink); }
.timeline-label { color: var(--muted); font-size: 0.85rem; }

@media (min-width: 720px) {
  .timeline { flex-direction: row; align-items: flex-start; }
  .timeline-step { flex: 1; flex-direction: column; align-items: center; text-align: center; position: relative; gap: var(--space-2); }
  .timeline-step:not(:first-child)::before {
    content: "";
    position: absolute;
    top: 8px; right: 50%;
    width: 100%; height: 2px;
    border-radius: 2px;
    background: var(--line);
    z-index: 0;
  }
  .timeline-step.is-done:not(:first-child)::before,
  .timeline-step.is-current:not(:first-child)::before { background: var(--pine); }
  .timeline-dot { position: relative; z-index: 1; width: 16px; height: 16px; }
  .timeline-label { font-size: 0.78rem; }
}

/* ---------- Progress ---------- */

.progress-track {
  height: 8px;
  border-radius: 999px;
  background: #EFE7D6;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--pine) calc(100% - 14px), var(--glow) calc(100% - 14px));
  animation: fillBar 1.1s var(--ease) .7s both;
}

.progress-pct { font-family: var(--display); font-weight: 500; color: var(--link); }

/* Onboarding flow thin bar (flush under header) */
.ob-flow-progress { height: 5px; background: var(--line); }
.ob-flow-progress .progress-fill-flush {
  height: 100%;
  background: var(--clay);
  border-radius: 0 999px 999px 0;
  transition: width .4s var(--ease);
}
.ob-flow-progress.is-complete .progress-fill-flush { background: var(--glow); border-radius: 0; }

/* ---------- Lists / rows ---------- */

.list { list-style: none; margin: 0; padding: 0; }

.list-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 6px 22px;
}

.list-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  padding: 15px 0;
  border-bottom: 1px solid var(--line);
}

.list-item:last-child { border-bottom: none; }
.list-item-main { flex: 1 1 220px; min-width: 0; }
.list-item-title { font-weight: 700; font-size: 14.5px; }
.list-item-meta {
  font-family: var(--mono);
  color: var(--muted);
  font-size: var(--fs-xs);
  margin-top: 2px;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.row-link { display: block; width: 100%; text-align: left; background: none; border: none; padding: 0; cursor: pointer; font-family: var(--font); color: inherit; }

/* ---------- Threads (edit requests) ---------- */

.thread {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  margin-bottom: var(--space-3);
  overflow: hidden;
}

.thread-header { padding: 18px 22px; cursor: pointer; background: transparent; }
.thread-header:hover { background: rgba(35,32,28,.02); }

.thread-body {
  padding: 20px 22px;
  border-top: 1px solid var(--line);
  background: var(--cream);
}

.comment {
  padding: 14px 16px;
  margin-bottom: var(--space-2);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-bubble);
}

.comment-admin { background: #FBF3EE; border-color: #E8D5C9; }
.comment-meta {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.comment-admin .comment-meta { color: var(--link); }

/* ---------- Status messages ---------- */

.status-msg { font-size: 0.85rem; margin-top: var(--space-2); min-height: 1.2em; }
.status-msg.is-error { color: var(--danger); }
.status-msg.is-ok { color: var(--ok); }
.status-msg.is-pending { color: var(--muted); }

/* ---------- Website preview ---------- */

.preview-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
  margin-bottom: var(--space-6);
}

.preview-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--ink);
  color: var(--cream);
  padding: 10px 20px;
  font-size: 12.5px;
}

.preview-dots { display: flex; gap: 5px; margin-right: 10px; }
.preview-dots span { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.preview-dots .d1 { background: var(--clay); }
.preview-dots .d2 { background: var(--glow); }
.preview-dots .d3 { background: var(--ok); }

.preview-url { font-family: var(--mono); font-size: var(--fs-xs); color: rgba(247,241,230,.75); }
.preview-bar-actions { display: flex; gap: 18px; align-items: center; }
.preview-bar a { color: var(--cream); font-weight: 600; text-decoration: none; }
.preview-bar a:hover { text-decoration: underline; color: var(--cream); }
.preview-feedback-link { color: var(--glow) !important; }

.preview-frame-wrap { aspect-ratio: 16 / 10; background: var(--surface-sunken); }
.preview-frame-wrap iframe { width: 100%; height: 100%; border: none; display: block; }

@media (max-width: 640px) {
  /* 16:10 leaves only a ~230px sliver at phone widths — go portrait instead */
  .preview-frame-wrap { aspect-ratio: auto; height: 62vh; max-height: 560px; }
}

/* ---------- Drop zone ---------- */

.dropzone {
  border: 2px dashed var(--line-strong);
  border-radius: var(--r-card);
  background: var(--card);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 34px 20px;
  cursor: pointer;
  text-align: center;
  transition: border-color .2s;
  width: 100%;
}

.dropzone:hover, .dropzone:focus-visible { border-color: var(--clay); }
.dropzone-title { font-size: var(--fs-base); font-weight: 700; color: var(--ink); }
.dropzone-sub {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- Stat tiles ---------- */

.tiles-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

@media (min-width: 720px) { .tiles-row { grid-template-columns: repeat(4, 1fr); } }

.stat-tile {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 18px 20px;
  transition: transform .25s var(--ease), box-shadow .25s;
}

a.stat-tile { display: block; color: inherit; text-decoration: none; }
a.stat-tile:hover { transform: translateY(-3px); box-shadow: 0 10px 28px rgba(35,32,28,.09); }
.stat-tile.is-attention { border-left: 3px solid var(--clay); }
.stat-tile.is-attention .stat-number,
.stat-tile.is-attention .stat-figure { color: var(--clay-dark); }

.stat-number {
  font-family: var(--display);
  font-size: 1.9rem;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.1;
}

.stat-label {
  font-family: var(--font);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--muted);
  margin-top: 6px;
}

.stat-delta { font-size: 0.82rem; margin-top: 8px; font-weight: 600; color: var(--muted); }
.stat-delta.is-up { color: var(--ok); }
.stat-delta.is-down { color: var(--clay-dark); }

.stat-tile-wide {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 12px 20px;
  font-size: 0.9rem;
  color: var(--muted);
  margin-bottom: var(--space-4);
}

/* ---------- Onboarding focused flow ---------- */

main.ob-flow-main { max-width: none; padding: 0; display: flex; flex-direction: column; }
.ob-stage-wrap { flex: 1; display: flex; flex-direction: column; max-width: 1080px; margin: 0 auto; width: 100%; padding: 0 var(--space-5); }

.ob-stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-7) var(--space-4) var(--space-5);
}

.ob-stage-body { width: 100%; max-width: 640px; transition: opacity .25s var(--ease), transform .25s var(--ease); }
.ob-stage-body.leaving  { opacity: 0; transform: translateY(-16px); }
.ob-stage-body.entering { opacity: 0; transform: translateY(16px); }

.ob-eyebrow {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}

.ob-item-heading {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.7rem, 4vw, 2.25rem);
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 12px 0 0;
  line-height: 1.12;
}

.ob-item-copy { font-size: 14.5px; color: var(--muted); max-width: 520px; margin: 10px auto 0; line-height: 1.55; }

.ob-interact { margin-top: 28px; display: flex; flex-direction: column; gap: var(--space-4); align-items: center; }
.ob-interact-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; justify-content: center; }
.ob-enter-hint { font-size: 12.5px; color: var(--muted); }
.ob-enter-hint strong { color: var(--ink); }
.ob-done-note { font-size: var(--fs-sm); color: var(--muted); }

.ob-upload-preview { margin-bottom: 12px; }
.ob-upload-thumb {
  display: block; max-width: 220px; max-height: 160px; width: auto; height: auto;
  border-radius: var(--r-card); border: 1px solid var(--line); object-fit: contain; background: var(--cream);
}

.ob-dropzone { max-width: 520px; padding: 36px 20px; }
.ob-dropzone-filename { font-size: var(--fs-sm); color: var(--pine); font-weight: 600; }

.ob-flow-textarea { min-height: 160px; font-size: 1.05rem; text-align: left; }

.ob-stage-nav { display: flex; justify-content: space-between; padding: 2px var(--space-3) var(--space-5); }
.ob-nav-btn {
  background: none; border: none;
  font-family: var(--font); font-size: var(--fs-sm); font-weight: 600;
  color: var(--link);
  padding: 10px 14px; min-height: 44px;
  border-radius: 999px;
  cursor: pointer;
  transition: background .2s;
}
.ob-nav-btn:hover { background: rgba(168,80,40,.08); }
.ob-nav-btn:disabled { color: var(--line-strong); cursor: default; background: none; }

.ob-badge {
  width: 52px; height: 52px;
  border-radius: 999px;
  background: rgba(224,163,78,.16);
  border: 1px solid var(--glow);
  color: var(--glow-ink);
  display: flex; align-items: center; justify-content: center;
  font-size: 22px;
  margin: 0 auto;
}

/* Note-item minimum-length feedback: a nudge while short, a quiet
   checkmark once met -- never a raw count, never red before the client
   has tried to submit (that's #obFlowStatus's job). */
.ob-note-counter { font-size: 12.5px; color: var(--muted); margin: 8px 0 0; text-align: left; }
.ob-note-counter.is-met { color: var(--ok); font-weight: 600; }

/* Admin's "send this back" reason, shown above the textarea being reopened */
.ob-reopen-callout {
  background: rgba(224,163,78,.12);
  border: 1px solid var(--glow);
  border-radius: var(--r-card);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-3);
  font-size: 0.88rem;
  color: var(--glow-ink);
  text-align: left;
}
.ob-reopen-callout strong { color: var(--ink); }

/* Wrap-around "Still to do" interstitial */
.ob-remaining-list {
  list-style: none;
  margin: 20px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
}
.ob-remaining-item { margin: 0; }
.ob-remaining-jump {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--cream);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-card);
  padding: 12px 16px;
  min-height: 44px;
  font-family: var(--font);
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
  transition: border-color .2s, background .2s;
}
.ob-remaining-jump:hover { border-color: var(--clay); background: rgba(199,91,57,.05); }
.ob-required-marker {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--glow-ink);
  background: rgba(224,163,78,.16);
  border-radius: 999px;
  padding: 3px 8px;
  flex: none;
}

/* ---------- Auth page ---------- */

body.auth-body { background: var(--pine); }

.auth-shell { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-5); gap: 26px; }

.auth-card {
  width: 100%;
  max-width: 440px;
  background: var(--cream);
  border-radius: var(--r-shell);
  padding: 40px 40px 34px;
  box-shadow: 0 20px 50px rgba(0,0,0,.25);
  animation: fadeUp .7s var(--ease) both;
}

@media (max-width: 480px) {
  .auth-shell { padding: 12px; }
  .auth-card { padding: 28px 20px; }
}

.auth-brand { display: flex; align-items: baseline; gap: 8px; justify-content: center; }
.auth-brand .wordmark-serif { color: var(--ink); font-size: 24px; }
.auth-brand .wordmark-mono { color: var(--link); }

.auth-tagline { font-size: 13.5px; color: var(--muted); text-align: center; margin: 10px 0 28px; line-height: 1.5; }

.auth-footnote {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(247,241,230,.75);
  letter-spacing: .06em;
  animation: fadeUp .6s var(--ease) .2s both;
}

.auth-toggle {
  background: none; border: none;
  color: var(--link);
  font-family: var(--font);
  font-size: var(--fs-sm); font-weight: 600;
  cursor: pointer;
  padding: var(--space-2);
  min-height: 44px;
  display: block;
  margin: 10px auto 0;
}

.auth-toggle:hover { text-decoration: underline; }

.auth-badge {
  width: 44px; height: 44px;
  border-radius: 999px;
  background: rgba(224,163,78,.16);
  border: 1px solid var(--glow);
  color: var(--glow-ink);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-lg);
  margin: 24px auto 14px;
}

/* ---------- Contact card ---------- */

.contact-card { display: flex; align-items: center; gap: var(--space-4); }
.contact-photo { width: 72px; height: 72px; object-fit: cover; border-radius: 50%; flex: none; }
.contact-card h3 { margin: 0 0 var(--space-1); font-size: 1.1rem; }
.contact-card p { margin: 0; color: var(--muted); font-size: 0.88rem; }

/* ---------- Utility ---------- */

.muted { color: var(--muted); }
.mt-0 { margin-top: 0; }
.flex-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.section-title { font-family: var(--display); font-size: 1.5rem; font-weight: 600; color: var(--ink); margin: var(--space-6) 0 var(--space-3); }

/* ============================================================
   Page-specific additions (mockup elements with no class yet)
   ============================================================ */

/* Sign-in — "link sent" state (no class existed for its inner copy) */
.auth-sent-title { font-size: var(--fs-base); font-weight: 700; color: var(--ink); text-align: center; margin: 0; }
.auth-sent-copy { font-size: 13.5px; color: var(--muted); text-align: center; margin-top: 8px; line-height: 1.55; }

/* Dashboard — "Project status" / "Getting started" side-by-side grid */
.dash-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
.dash-grid .card { margin-bottom: 0; }
@media (min-width: 860px) {
  .dash-grid { grid-template-columns: 1.5fr 1fr; }
}

/* Empty state — "Account not linked" glyph + title (Empty & Error States mockup) */
.empty-state-glyph { font-family: var(--display); font-size: 30px; color: var(--line-strong); line-height: 1; }
.empty-state-title { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--ink); margin: 10px 0 0; }

/* Generic loading line + visually-hidden label, used across pages */
.page-loading { color: var(--muted); font-size: 0.9rem; padding: var(--space-4) 0; }
.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;
}

/* ============================================================
   Page-specific additions — website / files / reports / admin
   redesign pass (Aug 2026). Small helpers layered on top of the
   base system above; nothing here duplicates an existing token.
   ============================================================ */

/* Thread expand/collapse indicator (website + admin threads) */
.thread-arrow { flex: none; color: var(--link); font-size: 14px; }

/* Pill comment-composer input (website thread reply box) */
.comment-input { border-radius: 999px; }

/* Files dropzone "browse" trigger word */
.dropzone-browse { color: var(--link); text-decoration: underline; cursor: pointer; }

/* Admin console two-column layout */
.admin-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
  align-items: start;
}

@media (min-width: 960px) {
  .admin-grid { grid-template-columns: 1fr 372px; }
}

.admin-col { display: flex; flex-direction: column; gap: var(--space-5); }

/* Per-client Stage / Staging URL / Live URL / Save row */
.client-fields-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  align-items: end;
  margin-top: 14px;
}

@media (min-width: 640px) {
  .client-fields-grid { grid-template-columns: 150px 1fr 1fr auto; }
}

.client-fields-grid .field { margin-bottom: 0; }

/* Mono-styled URL inputs (staging/live) */
.input-mono { font-family: var(--mono); font-size: var(--fs-xs); }

/* Dashed separator above the onboarding "add item" mini-form */
.ob-add-form { border-top: 1px dashed var(--line-strong); margin-top: 6px; padding-top: 14px; }

/* ============================================================
   Responsive spacing pass (Aug 2026) — desktop + mobile QA fixes
   ============================================================ */

/* Pill nav: never show a scrollbar when it overflows on small screens */
.site-nav { scrollbar-width: none; }
.site-nav::-webkit-scrollbar { display: none; height: 0; }

/* Fade the trailing edge of horizontally-scrolling pill navs on small
   screens as a scroll affordance, since the scrollbar itself is hidden */
@media (max-width: 640px) {
  .site-nav, .tabbar {
    mask-image: linear-gradient(to right, black calc(100% - 28px), transparent);
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 28px), transparent);
    /* Enough trailing padding that the last pill can scroll fully clear
       of the 28px fade instead of sitting clipped under it at max scroll */
    padding-right: 32px;
  }
}

/* Compact pills below 480px so all four client links fit a 390px screen
   (the Admin pill still scrolls into view — scrollbar stays hidden) */
@media (max-width: 480px) {
  .site-header__inner { padding-left: var(--space-4); padding-right: var(--space-4); }
  .site-nav { gap: 4px; }
  .site-nav a { padding: 8px 12px; font-size: 12.5px; }
}

/* Dashboard "Project status": the card stretches to match the taller
   "Getting started" card — float the stepper into the leftover space
   instead of leaving a void under it */
.dash-grid .card:first-child { display: flex; flex-direction: column; }
.dash-grid .card:first-child .timeline { margin-top: auto; margin-bottom: auto; }

/* Contact card (Nate) stacks cleanly on small screens */
@media (max-width: 640px) {
  .contact-card { flex-direction: column; align-items: flex-start; }
}

/* Edit-request rows: on small screens the status chip takes its own line
   so the title gets the full card width (inline flex:1 needs !important) */
@media (max-width: 640px) {
  .thread-header { flex-wrap: wrap; }
  .thread-header > span:nth-child(2) { flex: 1 1 100% !important; order: 3; }
  .thread-header .thread-arrow { margin-left: auto; }
}

/* Onboarding: keyboard hint is noise on touch screens */
@media (max-width: 640px) {
  .ob-enter-hint { display: none; }
}

/* Onboarding: give the reopen callout and "still to do" rows room to
   wrap instead of squeezing the required marker off the edge at
   narrow (390px-class) widths */
@media (max-width: 480px) {
  .ob-remaining-jump { flex-wrap: wrap; }
  .ob-reopen-callout, .ob-note-counter { font-size: var(--fs-sm); }
}

/* Dashboard rhythm: kept uniform with every other page's .card spacing
   (16px, --space-4) — a prior "more air" 24px override on just these two
   elements broke the vertical rhythm partway down the page (flagged by
   Nate 2026-08-11: "boxes aren't properly spaced"). Margin-bottom only,
   matching .card's convention, so collapsing behaves the same everywhere. */
.dash-grid { margin: 0 0 var(--space-4); }
.dash-tiles { margin: 0 0 var(--space-4); }

/* ============================================================
   "Point something out" — screenshot markup (visual feedback v1)
   ============================================================ */

.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }

.annotator-card { margin-bottom: var(--space-4); }

.ann-close {
  background: none; border: none; cursor: pointer;
  color: var(--muted); font-size: var(--fs-md); line-height: 1;
  padding: 8px; min-height: 44px; min-width: 44px;
}
.ann-close:hover { color: var(--ink); }

.ann-pill-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.ann-pill {
  background: var(--cream); border: 1px solid var(--line-strong);
  border-radius: 999px; padding: 8px 16px;
  font-family: var(--font); font-size: var(--fs-sm); font-weight: 600;
  color: var(--ink); cursor: pointer; min-height: 36px;
  transition: background .2s, border-color .2s;
}
.ann-pill:hover { border-color: var(--clay); }
.ann-pill.is-active { background: var(--pine); border-color: var(--pine); color: var(--cream); }

.ann-vp-row { display: flex; gap: 16px; margin-bottom: 12px; }
.ann-vp { font-size: var(--fs-sm); color: var(--muted); display: flex; align-items: center; gap: 6px; cursor: pointer; }

.ann-upload {
  display: inline-block; font-size: var(--fs-sm); font-weight: 600;
  color: var(--link); text-decoration: underline; cursor: pointer;
  padding: 6px 0; margin-bottom: 4px;
}

.ann-toolbar {
  display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
  margin: 14px 0 10px;
}
.ann-toolbar-gap { flex: 1; }
.ann-tool {
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: 999px; padding: 8px 14px;
  font-family: var(--font); font-size: 12.5px; font-weight: 600;
  color: var(--ink); cursor: pointer; min-height: 36px;
  transition: background .2s, border-color .2s, color .2s;
}
.ann-tool:hover { border-color: var(--clay); }
.ann-tool.is-active { background: var(--clay-fill); border-color: var(--clay-fill); color: var(--on-fill); }

.ann-canvas-wrap {
  border: 1px solid var(--line-strong); border-radius: 10px;
  overflow: auto; max-height: 70vh; background: var(--surface-sunken);
  line-height: 0;
}
.ann-canvas-wrap canvas { cursor: crosshair; display: block; }

.ann-pin-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.ann-pin-num {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  background: var(--clay-fill); color: var(--on-fill);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-sm); font-weight: 700;
}
.ann-pin-input { flex: 1; margin: 0; }

/* Annotated screenshot shown inside edit-request threads */
.annotation-link { display: block; margin-bottom: 14px; line-height: 0; }
.annotation-img {
  max-width: 100%; max-height: 620px;
  border: 1px solid var(--line-strong); border-radius: 10px;
  background: var(--surface-sunken);
}

/* ============================================================
   Live pins on the site preview (visual feedback v2)
   ============================================================ */

.preview-pin-toggle {
  background: transparent;
  border: 1px solid rgba(247,241,230,.4);
  border-radius: 999px;
  color: var(--cream);
  font-family: var(--font);
  font-size: var(--fs-xs); font-weight: 600;
  padding: 5px 12px;
  cursor: pointer;
  transition: background .2s, border-color .2s;
}
.preview-pin-toggle:hover { border-color: var(--cream); }
.preview-pin-toggle.is-active { background: var(--clay-fill); border-color: var(--clay-fill); }

.pin-composer { margin-top: var(--space-4); }
.pin-label {
  flex: none;
  max-width: 180px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; font-weight: 600; color: var(--muted);
}
.pin-remove {
  flex: none; background: none; border: none; cursor: pointer;
  color: var(--muted); font-size: var(--fs-sm); padding: 8px;
}
.pin-remove:hover { color: var(--ink); }

/* Pin lists inside threads */
.thread-pins { margin-bottom: 12px; }
.thread-pin-row {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 7px 0; font-size: 14px;
}
.thread-pin-row .ann-pin-num { margin-top: 1px; }
.thread-pin-row .pin-label { max-width: none; white-space: normal; color: var(--ink); }

/* ============================================================
   Tier 2 — approvals + GBP snapshot
   ============================================================ */

.approval-card { /* urgency carried by the glow chip, per design-system vocabulary */ }
.approval-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.approval-title { margin: 0 0 6px; font-size: 1.15rem; }
.approval-history { margin-top: 4px; }
.approval-history-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 0; border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.approval-history-row:last-child { border-bottom: none; }
.approval-history-title { font-weight: 600; color: var(--ink); }

.gbp-card { /* mono eyebrow carries the accent, per design-system vocabulary */ }
.gbp-head {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 10px;
}
.gbp-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.gbp-rating { font-family: var(--display); font-size: 34px; font-weight: 600; color: var(--ink); line-height: 1; }
.gbp-stars { color: var(--glow-ink); font-size: var(--fs-lg); letter-spacing: 2px; }
.gbp-reviews { color: var(--muted); font-size: 14px; }
.gbp-delta { color: var(--ok); font-weight: 600; font-size: 12.5px; }
.gbp-link { margin-left: auto; }

/* ============================================================
   v3.1 — Review engine (reviews.html)
   ============================================================ */

.review-link-row { display: flex; gap: 10px; flex-wrap: wrap; }
.review-link-row input { flex: 1; min-width: 220px; margin: 0; }

/* The printable counter card */
.qr-card-stage { display: flex; justify-content: center; padding: 18px 0 6px; }
.qr-card {
  width: 340px;
  background: var(--pine);
  color: var(--cream);
  border-radius: var(--r-card);
  padding: 30px 28px 24px;
  text-align: center;
}
.qr-card-eyebrow {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--glow);
}
.qr-card-title {
  font-family: var(--display);
  font-size: 26px; font-weight: 600;
  margin: 8px 0 6px;
}
.qr-card-sub { font-size: 13.5px; line-height: 1.5; color: rgba(247,241,230,.8); margin-bottom: 18px; }
.qr-code-holder {
  display: inline-block;
  background: var(--card);
  padding: 14px;                 /* quiet zone so scanners read it cleanly */
  border-radius: 10px;
  line-height: 0;
}
.qr-code-holder img, .qr-code-holder canvas { display: block; }
.qr-card-foot {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: rgba(247,241,230,.6);
  margin-top: 16px;
}

/* Ask templates */
.ask-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-4); }
@media (min-width: 760px) { .ask-grid { grid-template-columns: 1fr 1fr; } }
.ask-label {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.ask-text {
  font-family: var(--font);
  font-size: 13.5px; line-height: 1.55;
  white-space: pre-wrap;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 14px 16px;
  margin: 0 0 10px;
  color: var(--ink);
}

/* Print: only the counter card, centered on the page */
@media print {
  /* Only hijack printing on pages that actually contain the review counter
     card (reviews / resources). Without the :has() guard this blanked EVERY
     page — portal.css loads everywhere — so Ctrl+P on the dashboard,
     performance page, or work log printed empty paper. */
  body:has(.qr-card) * { visibility: hidden; }
  body:has(.qr-card) .qr-card, body:has(.qr-card) .qr-card * { visibility: visible; }
  .qr-card {
    position: absolute;
    left: 50%; top: 60px;
    transform: translateX(-50%);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
}

/* QR CDN fallback: show the raw link inside the card instead of an empty box */
.qr-fallback {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--ink);
  line-height: 1.5;
  max-width: 200px;
  word-break: break-all;
  padding: 8px;
}

/* ============================================================
   v3.2 — Win alerts (celebration rows in the hero attention strip)
   ============================================================ */

.attention-row-win { color: var(--glow); font-weight: 700; }
.attention-row-win:hover { color: var(--glow); }
.attention-row-win .attention-arrow { color: var(--glow); }

/* ============================================================
   v3.3 — Referral card
   ============================================================ */

.referral-card { background: var(--cream); }
.referral-copy { font-size: 14.5px; line-height: 1.6; color: var(--ink); margin: 4px 0 14px; max-width: 560px; }

/* ============================================================
   v3.4 — polish pack
   ============================================================ */

/* Resolved pins read as done, not deleted */
.pin-resolved .pin-label, .pin-resolved span { color: var(--muted); }
.pin-resolved .pin-label { text-decoration: line-through; }
.pin-resolved .ann-pin-num { background: var(--line-strong); }
.thread-pin-row .pin-resolve-btn { margin-left: auto; flex: none; }

/* ============================================================
   v4.0 — Admin console (admin-home.html + admin-client.html)
   ============================================================ */

/* Two-column layout reused across both pages (to-dos/add-client,
   overview facts/watch, publish-report/upload-vault, site/private) */
.console-two-col {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
  align-items: start;
}
@media (min-width: 860px) {
  .console-two-col { grid-template-columns: 1fr 1fr; }
}
.console-two-col .card { margin-bottom: 0; }

/* Modifier for a .console-two-col that follows a section-title section
   directly (admin-home.html's "Your to-dos / Add client" row, after
   "Clients") — it had no margin-top of its own, so it sat flush against
   the section above with a 0px gap. Give it the same top gap as every
   other section-title section (space-6, 32px) so the rhythm doesn't break
   partway down the page (flagged by Nate 2026-08-11: "boxes aren't
   properly spaced"). Scoped to this modifier rather than the base class so
   admin-client.html's two other .console-two-col rows — which follow
   .quick-links/.stat-row, not a section title, and read correctly at the
   normal 16px card gap — are untouched. */
.console-two-col--section { margin-top: var(--space-6); }

/* ---------- Search ---------- */

.console-search { position: relative; margin-bottom: var(--space-5); }
.console-search input {
  font-size: var(--fs-base);
  padding: 14px 18px;
  border-radius: 999px;
  border-color: var(--line-strong);
}
.console-search input:focus { border-color: var(--pine); }

.search-results {
  position: absolute;
  z-index: 20;
  top: calc(100% + 6px);
  left: 0; right: 0;
  max-height: 420px;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: 0 16px 40px rgba(35,32,28,.14);
  padding: 6px;
}

.search-group { padding: 8px; }
.search-group + .search-group { border-top: 1px solid var(--line); }
.search-group-label {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
  padding: 6px 8px 4px;
}

.search-hit {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 8px;
  border-radius: 10px;
  text-decoration: none;
  color: inherit;
}
a.search-hit:hover { background: var(--cream); }
.search-hit-title { font-size: 13.5px; font-weight: 600; color: var(--ink); }

/* ---------- Triage ("Needs you") ---------- */

.triage-list { display: flex; flex-direction: column; gap: 8px; }

.triage-row {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 14px 18px;
  text-decoration: none;
  color: inherit;
  transition: transform .2s var(--ease), box-shadow .2s;
}
a.triage-row:hover { transform: translateX(4px); box-shadow: 0 8px 22px rgba(35,32,28,.08); }

.triage-kind {
  flex: none;
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--muted);
  white-space: nowrap;
}
.triage-kind-approval { color: var(--glow-ink); border-color: var(--glow); background: rgba(224,163,78,.12); }
.triage-kind-newrequest { color: var(--clay-dark); border-color: var(--clay); background: rgba(199,91,57,.08); }
.triage-kind-pin { color: var(--link); border-color: var(--line-strong); }
.triage-kind-inprogress { color: var(--pine); border-color: var(--pine); background: rgba(31,61,52,.06); }
.triage-kind-todo { color: var(--clay-dark); border-color: var(--clay); background: rgba(199,91,57,.08); }

.triage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.triage-title { font-size: 14px; font-weight: 600; color: var(--ink); }
.triage-arrow { flex: none; color: var(--link); }

/* ---------- This-month cadence table ---------- */

.cadence-head {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 14px;
}

.cadence-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.cadence-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.cadence-table th, .cadence-table td { padding: 10px 8px; text-align: left; border-bottom: 1px solid var(--line); vertical-align: middle; }
.cadence-table thead th {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--line-strong);
}
.cadence-table tbody tr:last-child td, .cadence-table tbody tr:last-child th { border-bottom: none; }
.cadence-table th[scope="row"] { font-weight: 700; }
.cadence-table th[scope="row"] a { color: var(--ink); text-decoration: none; }
.cadence-table th[scope="row"] a:hover { color: var(--link); }

.cad-ok { color: var(--ok); font-weight: 600; }
.cad-todo { color: var(--muted); }
.cad-late { color: var(--danger); font-weight: 700; }
.cad-na { color: var(--line-strong); }

/* ---------- Watch list ---------- */

.watch-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-3); }
@media (min-width: 760px) { .watch-grid { grid-template-columns: 1fr 1fr; } }

.watch-card { display: flex; flex-direction: column; gap: 8px; }
.watch-client { font-weight: 700; font-size: 14.5px; color: var(--ink); text-decoration: none; }
.watch-client:hover { color: var(--link); }

.flag-stack, .watch-card { display: flex; flex-wrap: wrap; gap: 8px; }
.watch-card { align-items: flex-start; }

.flag {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-xs); font-weight: 600;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid;
}
.flag-warn  { color: var(--glow-ink); border-color: var(--glow); background: rgba(224,163,78,.12); }
.flag-alert { color: var(--danger); border-color: #E39187; background: rgba(168,48,43,.08); }
.flag-link { text-decoration: none; }

/* ---------- Client cards ---------- */

.client-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-3); }
@media (min-width: 760px) { .client-grid { grid-template-columns: 1fr 1fr; } }
.archived-clients { margin-top: var(--space-3); }
.archived-clients > summary { cursor: pointer; color: var(--muted); font-size: 14px; list-style: revert; }
.archived-clients > summary:hover { color: inherit; }

.client-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-decoration: none;
  color: inherit;
  margin-bottom: 0;
}
.client-card:hover { transform: translateY(-3px); box-shadow: 0 10px 28px rgba(35,32,28,.09); }

.client-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.client-card-name { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--ink); }
.client-card-stage {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.client-card-counts { font-size: var(--fs-sm); color: var(--ink); font-weight: 600; }

/* ---------- Private to-dos ---------- */

.task-form { border-top: 1px dashed var(--line-strong); margin-top: 10px; padding-top: 14px; }

.task-check {
  flex: none;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--muted);
  cursor: pointer;
  font-size: var(--fs-sm);
  display: flex; align-items: center; justify-content: center;
  transition: border-color .2s, color .2s;
}
.task-check:hover { border-color: var(--ok); color: var(--ok); }

/* ---------- Client workspace tab bar ---------- */

.hero-back { color: var(--cream); opacity: .85; text-decoration: none; font-family: var(--mono); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.hero-back:hover { color: var(--cream); opacity: 1; }

.tabbar {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  border-bottom: 1px solid var(--line);
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 var(--space-6);
}
.tabbar::-webkit-scrollbar { display: none; height: 0; }
/* With the scrollbar hidden, a tab row wider than the viewport silently
   swallows its last tabs on a desktop with no horizontal scroll gesture:
   "Settings" (the 11th tab) was invisible at 1233px and nobody knew it
   existed. So the row wraps onto a second line by default, and only
   phones (the same 640px where the trailing-edge fade above applies)
   keep the swipe-to-scroll strip. Wrap is the default that phones opt
   OUT of, rather than desktop opting in above a min-width: two queries
   meeting at 640/641px leave fractional viewport widths (browser zoom)
   matching neither. */
.tabbar { flex-wrap: wrap; overflow-x: visible; row-gap: 0; }
@media (max-width: 640px) {
  .tabbar { flex-wrap: nowrap; overflow-x: auto; }
}

.tab {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 14px 16px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  transition: color .2s, border-color .2s;
}
.tab:hover { color: var(--ink); }
.tab.is-active { color: var(--pine); border-bottom-color: var(--clay); }

.tab-count {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 700;
  background: var(--clay-fill);
  color: var(--on-fill);
  border-radius: 999px;
  min-width: 17px;
  padding: 1px 5px;
  text-align: center;
  line-height: 1.5;
}
.tab.is-active .tab-count { background: var(--pine); }

/* ---------- Overview: stat row + facts + private card ---------- */

.stat-row { display: grid; grid-template-columns: repeat(1, 1fr); gap: var(--space-3); margin-bottom: var(--space-4); }
@media (min-width: 640px) { .stat-row { grid-template-columns: repeat(3, 1fr); } }

.stat-value {
  font-family: var(--display);
  font-size: 1.9rem;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.1;
  margin-top: 4px;
}

.quick-links { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: var(--space-4); }

.fact-list { list-style: none; margin: 0; padding: 0; }
.fact-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13.5px;
}
.fact-row:last-child { border-bottom: none; }
.fact-label { color: var(--muted); flex: none; }
.fact-value { color: var(--ink); font-weight: 600; text-align: right; }

.private-card { background: var(--cream); border-style: dashed; border-color: var(--line-strong); }
.private-label {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
}

/* ---------- Activity feed ---------- */

.activity-month-label {
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
  margin: var(--space-5) 0 8px;
}
.activity-month-label:first-child { margin-top: 0; }

.activity-timeline {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 4px 20px;
  margin-bottom: var(--space-3);
}

.activity-row {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.activity-row:last-child { border-bottom: none; }

.activity-date {
  flex: none;
  width: 84px;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--muted);
}

.activity-kind {
  flex: none;
  font-family: var(--mono);
  font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--muted);
}
.activity-work     { color: var(--pine); border-color: var(--pine); background: rgba(31,61,52,.06); }
.activity-request  { color: var(--clay-dark); border-color: var(--clay); background: rgba(199,91,57,.08); }
.activity-approval { color: var(--glow-ink); border-color: var(--glow); background: rgba(224,163,78,.12); }
.activity-pin      { color: var(--link); border-color: var(--line-strong); }
.activity-report   { color: var(--ok); border-color: var(--ok); background: rgba(46,107,79,.08); }
.activity-win       { color: var(--glow-ink); border-color: var(--glow); background: rgba(224,163,78,.18); font-weight: 700; }

.activity-main { flex: 1; min-width: 0; }
.activity-title { display: block; font-size: 13.5px; font-weight: 600; color: var(--ink); }

/* ---------- Work log ---------- */

.worklog-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3) var(--space-4);
  align-items: end;
}
@media (min-width: 760px) {
  .worklog-form { grid-template-columns: 2fr 1fr 1fr 1fr auto; }
}
.field-wide { grid-column: 1 / -1; }
@media (min-width: 760px) {
  .worklog-form .field-wide { grid-column: 1 / 3; }
}
.worklog-form .field { margin-bottom: 0; }
.worklog-form button { align-self: end; }

/* ---------- Onboarding admin tick ---------- */

.ob-tick { color: var(--line-strong); font-size: var(--fs-sm); width: 16px; flex: none; }
.ob-tick.is-done { color: var(--pine); }
.list-item-title.is-struck { color: var(--muted); text-decoration: line-through; }

/* Reopen reason: revealed inline under a done checklist item, collapsed
   until "Reopen" is clicked (see renderOnboarding in admin-client.html) */
.ob-reopen-form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.ob-reopen-form input { flex: 1 1 220px; min-width: 0; margin: 0; }
.ob-reopen-form .status-msg { width: 100%; margin: 2px 0 0; }

/* ---------- Settings grid ---------- */

.settings-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3) var(--space-4);
}
@media (min-width: 640px) {
  .settings-grid { grid-template-columns: 1fr 1fr; }
}
.settings-grid .field { margin-bottom: 0; }
.settings-grid button { grid-column: 1 / -1; justify-self: start; }

/* ============================================================
   v3.6 — Ask Pagoda (dashboard.html widget)
   ============================================================ */

.ask-pagoda-card { background: var(--cream); }
.ask-pagoda-form { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.ask-pagoda-input { flex: 1 1 240px; margin-bottom: 0; }
.ask-pagoda-form button { flex: none; }
.ask-pagoda-answer {
  margin-top: var(--space-3);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink);
}
.ask-pagoda-answer:empty { margin-top: 0; }
.ask-pagoda-answer.is-error { color: var(--danger); }

/* ============================================================
   v4.0 — Rank grid map (rank-grid.html + admin-client.html tab)
   ============================================================ */

.rank-grid {
  display: grid;
  grid-template-columns: repeat(var(--rg-size, 5), 1fr);
  gap: 6px;
  max-width: 420px;
  margin: 0 auto;
}

.rank-cell {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 14px;
  border: 1px solid var(--line-strong);
}

.rank-cell-green  { background: rgba(46,107,79,.16); border-color: var(--ok); color: var(--ok); }
.rank-cell-yellow { background: rgba(224,163,78,.20); border-color: var(--glow); color: var(--glow-ink); }
.rank-cell-red    { background: rgba(199,91,57,.14); border-color: var(--clay); color: var(--clay-dark); }
.rank-cell-gray   { background: var(--cream); border-color: var(--line-strong); color: var(--muted); }

.rank-grid-input {
  display: grid;
  gap: 6px;
  max-width: 560px;
  margin: 0 auto;
}
.rank-grid-input-cell { display: flex; flex-direction: column; gap: 3px; }
.rank-grid-input-cell input[type="number"] {
  min-height: 40px;
  padding: 6px;
  text-align: center;
  font-family: var(--mono);
}
.rank-grid-input-cell input[type="text"] {
  min-height: 28px;
  padding: 3px 6px;
  text-align: center;
  font-size: var(--fs-xs);
}

.rank-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-4);
  font-size: var(--fs-sm);
  color: var(--muted);
}
.rank-legend-item { display: flex; align-items: center; gap: 8px; }
.rank-legend-swatch {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  border: 1px solid var(--line-strong);
  flex: none;
}
.rank-legend-swatch.rank-cell-green  { background: rgba(46,107,79,.16); border-color: var(--ok); }
.rank-legend-swatch.rank-cell-yellow { background: rgba(224,163,78,.20); border-color: var(--glow); }
.rank-legend-swatch.rank-cell-red    { background: rgba(199,91,57,.14); border-color: var(--clay); }
.rank-legend-swatch.rank-cell-gray   { background: var(--cream); border-color: var(--line-strong); }

.rank-grid-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

/* Center-cell pin (the business's own location) -- added 2026-08-11 after
   Nate flagged the grid as unclear without it ("not even sure how to read
   the Where you rank grid"). Ringed in clay so it reads as "you are here"
   distinct from the green/yellow/red rank coloring. */
.rank-cell-center { position: relative; box-shadow: 0 0 0 2px var(--clay); }
.rank-cell-center::after {
  content: "📍";
  position: absolute;
  top: -10px; right: -8px;
  font-size: var(--fs-sm);
  line-height: 1;
}

/* Real map view (v4.3) -- replaces the grid above when the client has
   clients.lat/lng set; see Portal.renderRankGridView in portal.js. */
.rank-grid-map {
  height: 380px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
}

.rank-marker-pin {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 2px solid rgba(0,0,0,.25);
  font-family: var(--mono);
  font-weight: 700;
  font-size: var(--fs-xs);
  color: var(--on-fill);
  text-shadow: 0 1px 2px rgba(0,0,0,.55);
  box-shadow: 0 1px 4px rgba(0,0,0,.35);
}
.rank-marker-center .rank-marker-pin { box-shadow: 0 0 0 3px var(--clay), 0 1px 4px rgba(0,0,0,.35); }
.rank-marker-flag { position: absolute; top: -15px; right: -9px; font-size: 14px; line-height: 1; }

/* Compact keyword table -- performance.html's "Search terms" section.
   Replaces keywords.html's one-card-per-keyword grid, which doesn't scale
   past a handful of tracked phrases (TMT alone tracks 20). */
.kw-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.kw-table th {
  text-align: left;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0 10px 8px;
  border-bottom: 1px solid var(--line);
}
.kw-table td { padding: 12px 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.kw-table tr:last-child td { border-bottom: none; }
.kw-table .kw-phrase { font-weight: 700; }
.kw-table .kw-pos { font-family: var(--mono); font-weight: 700; font-size: var(--fs-base); }

/* Search terms table collapses to the top 5 best-ranked terms by default
   (performance.html, added 2026-08-11) -- the rest reveal via "See all". */
.kw-row-extra { display: none; }
.kw-table.is-expanded .kw-row-extra { display: table-row; }

/* Map-box slot chip in the targets table. 1st gets the clay accent so the
   headline win reads at a glance. */
.kw-table .kw-mapbox { font-family: var(--mono); font-weight: 700; font-size: var(--fs-base); color: var(--pine); }
.kw-table .kw-mapbox--first { color: var(--clay); }
.kw-table .kw-trend .chip { white-space: nowrap; }

/* Mobile: neither table fits a phone width -- collapse each row into a
   stacked card instead of forcing horizontal scroll. The phrase is the
   card title; every other cell becomes a labeled value row (labels come
   from CSS content, matching each table's desktop <thead> text, so no
   markup duplication). Two tables, two label sets:
     .kw-table--targets  Phrase | Regular results | Google map top 3 | vs. last month
     .kw-table--real     Phrase | Visits from Google
   Added 2026-08-12 per Nate's mobile QA; reworked 2026-09-07 for the split. */
@media (max-width: 639px) {
  .kw-table thead { display: none; }
  .kw-table, .kw-table tbody, .kw-table tr, .kw-table td { display: block; width: 100%; }
  .kw-table tr { padding: 12px 10px; border-bottom: 1px solid var(--line); }
  .kw-table tr:last-child { border-bottom: none; }
  .kw-table td { padding: 0; border: none; }
  .kw-table .kw-phrase { padding-bottom: 8px; }

  .kw-table td:not(.kw-phrase) {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0;
  }
  .kw-table td:not(.kw-phrase)::before {
    font-family: var(--mono);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .kw-table--targets td:nth-child(2)::before { content: "Regular results"; }
  .kw-table--targets td:nth-child(3)::before { content: "Google map top 3"; }
  .kw-table--targets td:nth-child(4)::before { content: "vs. last month"; }
  .kw-table--real td:nth-child(2)::before { content: "Visits from Google"; }

  /* `.kw-table tr { display: block }` above outspecifies the one-class
     `.kw-row-extra { display: none }` rule, so without these the collapsed
     GSC rows leaked on phones regardless of the See-all state (pre-existing
     bug, surfaced by Macroscope on PR #65). Re-assert the expander here. */
  .kw-table tr.kw-row-extra { display: none; }
  .kw-table.is-expanded tr.kw-row-extra { display: block; }
}

/* Rank grid + backlink trend charts now render via the shared Pagoda
   Charts engine (css/pagoda-charts.css + js/pagoda-charts.js) — these
   two classes are the only pieces still used directly by
   Portal.renderRankTrendChart()/renderBacklinkTrendChart() in
   js/portal.js (a wrapper div and the "not enough history" empty
   state); the rest of the old hand-rolled SVG chart CSS lived here
   and has been superseded. */
.rank-trend-chart { max-width: 640px; margin: 0 auto; }
.rank-trend-empty { color: var(--muted); font-size: 14px; }

/* ============================================================
   Funnel wizard (Phase G, Session G1) — start.html's intake
   wizard + the admin "Build Brief" (admin-client.html). Sign-off
   item 3 (docs/FUNNEL-V2-PLAN.md §2): funnel-facing surfaces get
   an elevated, modern treatment, still inside these same tokens —
   no new palette, no forked design system.
   ============================================================ */

.wizard-shell { max-width: 640px; margin: 0 auto; }

.wizard-progress {
  display: flex;
  align-items: center;
  gap: 0;
  margin-bottom: var(--space-6);
}
.wizard-progress-step {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  position: relative;
}
.wizard-progress-step::before {
  content: "";
  position: absolute;
  top: 13px;
  left: -50%;
  width: 100%;
  height: 2px;
  background: var(--line);
  z-index: 0;
}
.wizard-progress-step:first-child::before { display: none; }
.wizard-progress-step.is-done::before { background: var(--glow); }
.wizard-progress-dot {
  position: relative;
  z-index: 1;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  border: 2px solid var(--line-strong);
  background: var(--card);
  color: var(--muted);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .25s var(--ease), border-color .25s var(--ease), color .25s var(--ease);
}
.wizard-progress-step.is-active .wizard-progress-dot {
  border-color: var(--clay);
  color: var(--clay);
  box-shadow: 0 0 0 4px rgba(199,91,57,.12);
}
.wizard-progress-step.is-done .wizard-progress-dot {
  border-color: var(--glow);
  background: var(--glow);
  color: var(--ink);
}
.wizard-progress-label {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}
.wizard-progress-step.is-active .wizard-progress-label { color: var(--ink); }

.wizard-step { animation: fadeUp .45s var(--ease) backwards; }
.wizard-step-title { margin-bottom: 4px; }
.wizard-step-hint { color: var(--muted); font-size: 13.5px; margin-top: -6px; margin-bottom: var(--space-5); }

.wizard-field-group {
  border-top: 1px solid var(--line);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
}
.wizard-field-group-title {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--link);
  margin-bottom: var(--space-3);
}

.wizard-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: var(--space-6);
}
.wizard-nav .btn { flex: none; }
/* FIX (G1 Feedback Round 1 QA, docs/G1-FEEDBACK-ROUND-1.md ground rules --
   found while walking the wizard before push): .btn sets its own
   `display: inline-flex`, which beats the UA stylesheet's
   `[hidden] { display: none }` on specificity tie-break (author rules
   win ties over UA rules) -- so backBtn.hidden/nextBtn.hidden/
   submitBtn.hidden in start.js were being silently ignored and EVERY
   nav button rendered on EVERY step, including "Send my answers" on
   step 1. Confirmed via getComputedStyle() during interactive QA. */
.wizard-nav .btn[hidden] { display: none; }
.wizard-nav-spacer { flex: 1 1 auto; }

.wizard-check-field {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
}
.wizard-check-field input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--clay); }

/* Confirm-mode "already answered" review rows — collapsed by default,
   click Edit to reopen that step's real inputs (FUNNEL-V2-PLAN.md §3.2:
   "confirm mode collapses ... only walks the steps with unanswered
   questions"). */
.wizard-review-card {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--card);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-4);
}
.wizard-review-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.wizard-review-head h3 { margin: 0; font-size: 1.05rem; }
.wizard-review-rows { margin-top: var(--space-3); }
.wizard-review-row { display: flex; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 13.5px; }
.wizard-review-row:last-child { border-bottom: none; }
.wizard-review-row-label { flex: 0 0 42%; color: var(--muted); }
/* FIX (Macroscope finding, Medium): a long unbroken value (a URL, a
   pasted token, a run-on word) has no natural break point, so a flex
   item's default min-width: auto let it push past its column instead
   of wrapping. min-width: 0 lets it actually shrink to the row; 
   overflow-wrap: anywhere allows a break mid-word/mid-URL as a last
   resort rather than overflowing. */
.wizard-review-row-value { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; color: var(--ink); white-space: pre-wrap; }

/* ---------- Admin Build Brief (admin-client.html) ---------- */

.brief-industry {
  display: inline-block;
  max-width: 100%;
  overflow-wrap: anywhere;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--glow-ink);
  background: rgba(224,163,78,.14);
  border: 1px solid var(--glow);
  border-radius: 999px;
  padding: 3px 12px;
  margin-bottom: var(--space-3);
}
.brief-group { margin-bottom: var(--space-5); }
.brief-group-title {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--link);
  margin-bottom: var(--space-2);
}
.brief-row { display: flex; gap: 14px; padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 13.5px; }
.brief-row:last-child { border-bottom: none; }
.brief-row-label { flex: 0 0 44%; color: var(--muted); }
.brief-row-value { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; color: var(--ink); white-space: pre-wrap; font-weight: 600; }

/* ============================================================
   G1 Feedback Round 1 additions (docs/G1-FEEDBACK-ROUND-1.md):
   services repeater rows (item 4), logo upload widget (item 6). Same
   tokens as the rest of the wizard/Build Brief block above -- no new
   palette, no forked design system.
   ============================================================ */

.wizard-service-rows label { display: block; margin-bottom: var(--space-2); }
.service-row-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.service-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
/* FIX (G1 Feedback Round 1 QA / Macroscope finding): a flex item's default
   min-width is auto (its content's intrinsic width), not 0 -- so these
   text inputs refused to shrink below that on a narrow (~320px) viewport
   and the row overflowed/clipped instead of wrapping. min-width: 0 lets
   the percentage flex-basis above actually take effect; flex-wrap above
   is the backstop for when even that isn't enough room. */
.service-row-name { flex: 1 1 60%; min-width: 0; }
.service-row-price { flex: 1 1 30%; min-width: 0; }
.service-row-name,
.service-row-price {
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-input, 10px);
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
}
.service-row-remove {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  font-size: var(--fs-md);
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.service-row-remove:disabled { opacity: 0.35; cursor: not-allowed; }
.service-row-add { margin-top: 2px; }

.wizard-logo-field .wizard-logo-preview {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--card);
}
/* FIX (G1 Feedback Round 1 QA -- same specificity tie-break lesson as the
   wizard-nav .btn[hidden] fix above): this rule's own `display: flex` beats
   the UA stylesheet's `[hidden] { display: none }` on a specificity tie, so
   JS setting logoPreviewWrap.hidden = true was being silently ignored and
   the empty preview card (with just a "Remove" link) rendered before any
   logo was ever attached. Found during interactive QA of the logo upload
   flow. */
.wizard-logo-field .wizard-logo-preview[hidden] { display: none; }
.wizard-logo-thumb {
  flex: none;
  width: 48px;
  height: 48px;
  object-fit: contain;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--on-fill);
}
.wizard-logo-meta { flex: 1 1 auto; min-width: 0; }
.wizard-logo-filename { margin: 0; font-weight: 600; font-size: 13.5px; color: var(--ink); overflow-wrap: anywhere; }
.wizard-logo-attached { margin: 2px 0 6px; font-size: 12.5px; color: var(--muted); }

/* ==========================================================================
   Funnel v2 — three-direction reveal (FUNNEL-V2-PLAN §4.4)
   The prospect-facing surface prospects judge us on: elevated + modern but
   built entirely from Pagoda tokens (no fork, no new framework). Motion is
   tasteful and reduced-motion-safe.
   ========================================================================== */

.reveal-head { margin: 0 0 var(--space-5); }
.reveal-head h2 { margin: 0 0 var(--space-2); }
.reveal-kicker {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--clay);
  margin: 0 0 var(--space-2);
}

/* Segmented direction switcher — the three named directions live here. */
.reveal-switcher {
  display: flex;
  gap: 6px;
  padding: 6px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 999px;
  margin-bottom: var(--space-4);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.reveal-seg {
  flex: 1 1 0;
  min-width: 128px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 10px 16px;
  border: none;
  background: transparent;
  border-radius: 999px;
  cursor: pointer;
  text-align: left;
  color: var(--muted);
  transition: background .25s var(--ease), color .25s var(--ease);
  font-family: var(--font);
}
.reveal-seg:hover { background: rgba(31,61,52,.06); color: var(--ink); }
.reveal-seg .reveal-seg-tag {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.reveal-seg .reveal-seg-name { font-size: 14px; font-weight: 700; line-height: 1.15; }
.reveal-seg.is-active { background: var(--pine); color: var(--cream); }
.reveal-seg.is-active .reveal-seg-tag { color: var(--glow); }
.reveal-seg.is-chosen { box-shadow: inset 0 0 0 2px var(--glow); }

/* Preview frame — carries the width toggle and pin toggle in its bar. */
.reveal-vp-toggle { display: inline-flex; gap: 4px; align-items: center; }
.reveal-vp {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(247,241,230,.7);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 4px 9px;
  cursor: pointer;
}
.reveal-vp.is-active { color: var(--cream); border-color: rgba(247,241,230,.4); background: rgba(247,241,230,.1); }

.reveal-frame-outer { background: var(--surface-sunken); padding: 0; transition: padding .3s var(--ease); }
.reveal-frame-outer.is-mobile { padding: 22px clamp(0px, 50% - 197px, 50%); }
.reveal-frame-wrap { aspect-ratio: 16 / 10; background: var(--surface-sunken); transition: aspect-ratio .3s var(--ease); }
.reveal-frame-outer.is-mobile .reveal-frame-wrap {
  aspect-ratio: 390 / 720;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(35,32,28,.18);
  border: 6px solid var(--ink);
}
.reveal-frame-wrap iframe { width: 100%; height: 100%; border: none; display: block; }
.reveal-frame-wrap.is-switching iframe { opacity: 0; }
.reveal-frame-wrap iframe { transition: opacity .28s var(--ease); }

/* Active-direction meta + the free choose CTA. */
.reveal-active { margin-top: var(--space-4); }
.reveal-active-world { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.reveal-active-world h3 { margin: 0; font-size: 1.35rem; }
.reveal-active-tag {
  font-family: var(--mono); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--clay);
}
.reveal-active-why { color: var(--muted); margin: 0 0 var(--space-4); max-width: 60ch; }

.reveal-choose-row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.reveal-choose-btn { min-width: 220px; }
.reveal-choose-hint { color: var(--muted); font-size: 0.86rem; margin: 0; }

.reveal-chosen-badge {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--mono); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ok); background: rgba(46,107,79,.1);
  border: 1px solid var(--ok); border-radius: 999px; padding: 6px 14px;
}

@media (max-width: 640px) {
  .reveal-seg { min-width: 116px; }
  .reveal-choose-btn { width: 100%; min-width: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .reveal-seg, .reveal-frame-outer, .reveal-frame-wrap,
  .reveal-frame-wrap iframe { transition: none; }
}

/* ---------- Document viewer overlay (Portal.openDocViewer) ---------- */
/* One overlay, lazily built and reused across opens (see js/portal.js).
   z-index sits above both #site-header/.site-nav (static, in normal flow,
   no z-index of their own) and .admin-preview-banner (also static flow) --
   400 is comfortably clear of the highest z-index already in use anywhere
   in this file (.search-results at 20), with headroom to spare. */
.docviewer-scrim {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 400;
  background: rgba(31,61,52,.55);
  backdrop-filter: blur(2px);
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
}
.docviewer-scrim.is-open { display: flex; }

.docviewer-panel {
  display: flex;
  flex-direction: column;
  width: min(920px, 94vw);
  height: 88vh;
  background: var(--card);
  border-radius: var(--r-shell);
  box-shadow: 0 20px 50px rgba(0,0,0,.25);
  overflow: hidden;
}

.docviewer-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line);
  flex: none;
}

.docviewer-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--pine);
}

.docviewer-actions { display: flex; align-items: center; gap: var(--space-2); flex: none; }

.docviewer-action {
  font-family: var(--font);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--pine);
  text-decoration: none;
  border: 1px solid var(--pine);
  border-radius: 999px;
  padding: 7px 14px;
  white-space: nowrap;
  transition: background .2s, color .2s;
}
.docviewer-action:hover { background: var(--pine); color: var(--cream); }

.docviewer-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: var(--fs-base);
  cursor: pointer;
  transition: background .2s, color .2s;
}
.docviewer-close:hover { background: rgba(35,32,28,.08); color: var(--ink); }

.docviewer-body { flex: 1 1 auto; min-height: 0; background: var(--cream); }

.docviewer-iframe { width: 100%; height: 100%; border: none; display: block; }

.docviewer-body.has-image {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  padding: var(--space-4);
}

.docviewer-img { max-width: 100%; max-height: 100%; object-fit: contain; }

@media (max-width: 640px) {
  .docviewer-scrim { padding: 0; }
  .docviewer-panel { width: 100vw; height: 100dvh; border-radius: 0; }
}

/* ============================================================
   Work log plain-language cards + dialog
   ============================================================ */

/* Clickable work-log row (worklog.html) -- a real <button> spanning the
   whole row, styled to read exactly like the existing .list-item rows
   so the interactive and non-interactive variants sit together cleanly
   in the same list. */
.work-list-item { padding: 0; }
.work-row-btn {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  padding: 15px 0;
  border: none;
  background: none;
  font-family: var(--font);
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.work-row-btn:hover .work-row-affordance,
.work-row-btn:focus-visible .work-row-affordance { color: var(--link); }

.work-row-btn:focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: -2px;
  border-radius: 6px;
}

.work-row-affordance {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-left: auto;
}

.work-row-chevron { font-size: var(--fs-base); line-height: 1; }

/* Title + meta are <span>s inside the button (phrasing content only),
   so stack them the way the <div> versions in plain rows stack. */
.work-row-btn .list-item-title,
.work-row-btn .list-item-meta { display: block; }

/* Shared work-log detail dialog -- one <dialog>, filled per click */
.work-dialog {
  max-width: 560px;
  width: calc(100% - 32px);
  max-height: 85vh;
  overflow-y: auto;
  padding: 28px 26px 26px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 24px 60px rgba(35,32,28,.22);
}

/* Belt and braces: never show a closed dialog, even where the browser
   has no native <dialog> styles. */
.work-dialog:not([open]) { display: none; }

.work-dialog::backdrop {
  background: rgba(31,61,52,.55); /* pine, semi-transparent */
}

@media (prefers-reduced-motion: no-preference) {
  .work-dialog {
    animation: workDialogIn .22s var(--ease);
  }
  .work-dialog::backdrop {
    animation: workDialogBackdropIn .22s var(--ease);
  }
}

@keyframes workDialogIn {
  from { opacity: 0; transform: scale(.97) translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@keyframes workDialogBackdropIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.work-dialog-close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  border-radius: 999px;
  cursor: pointer;
}
.work-dialog-close:hover { color: var(--ink); background: rgba(35,32,28,.06); }

/* overflow-wrap: long URLs/paths in a technical note or bullet would
   otherwise force a sideways scroll inside the dialog on a phone. */
.work-dialog-body { padding-right: 30px; overflow-wrap: anywhere; }

.work-dialog-eyebrow {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}

.work-dialog-heading {
  font-family: var(--display);
  font-size: 1.5rem;
  margin: 0 0 14px;
}

.work-dialog-bullets {
  margin: 0 0 16px;
  padding-left: 20px;
  color: var(--ink);
}
.work-dialog-bullets li { margin-bottom: 6px; line-height: 1.5; }
.work-dialog-bullets li:last-child { margin-bottom: 0; }

.work-dialog-why {
  background: rgba(224,163,78,.14);
  border: 1px solid var(--glow);
  border-radius: var(--r-card);
  padding: 14px 16px;
  margin: 0 0 18px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
}
.work-dialog-why-label {
  display: block;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--glow-ink);
  margin-bottom: 4px;
}

.work-dialog-tech {
  border-top: 1px solid var(--line);
  padding-top: 12px;
}
.work-dialog-tech summary {
  cursor: pointer;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--link);
  min-height: 44px;
  display: flex;
  align-items: center;
}
.work-dialog-tech-body {
  white-space: pre-wrap;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--muted);
  margin-top: 8px;
}

.work-dialog-foot {
  display: flex;
  justify-content: flex-end;
  margin-top: 22px;
}

@media (max-width: 480px) {
  .work-dialog { padding: 24px 18px 20px; }
  .work-dialog-body { padding-right: 26px; }
  .work-dialog-heading { font-size: 1.3rem; }
}

/* Dashboard "Recent work" fallback title clamp -- only applied when
   there's no plain_summary yet and the raw technical entry could run
   long; a real summary is already one short sentence. */
.list-item-title-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ============================================================
   Design-critique pass (Oct 2026) — shared contract classes
   ============================================================ */

/* Card headings never need a top margin override */
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }

/* Stack spacing utilities */
.stack-2 > * + * { margin-top: var(--space-2); }
.stack-3 > * + * { margin-top: var(--space-3); }
.stack-4 > * + * { margin-top: var(--space-4); }

/* The one big-number style */
.stat-figure {
  font-family: var(--display);
  font-size: 2rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--ink);
}

/* Longer secondary text in list rows (.list-item-meta stays for short stamps) */
.list-item-desc {
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.45;
  color: var(--muted);
  margin-top: 2px;
}

/* Muted one-line intro under a section title */
.section-lede {
  color: var(--muted);
  font-size: var(--fs-base);
  line-height: 1.5;
  margin: calc(-1 * var(--space-2)) 0 var(--space-4);
}

/* A whole card that is a link */
.nav-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: var(--space-4) var(--space-5);
  color: var(--ink);
  text-decoration: none;
  transition: transform .25s var(--ease), box-shadow .25s, border-color .2s;
}
.nav-card:hover { color: var(--ink); border-color: var(--line-strong); transform: translateY(-2px); box-shadow: 0 10px 28px rgba(35,32,28,.08); }
.nav-card h3 { margin: 0; color: var(--link); font-size: 1.15rem; }
.nav-card p { margin: 0; color: var(--muted); font-size: 14px; }

/* Small boxed notes / errors */
.inline-note, .inline-error {
  border-radius: var(--r-input);
  padding: var(--space-3) var(--space-4);
  font-size: 14px;
  line-height: 1.5;
  margin: var(--space-3) 0;
}
.inline-note { background: var(--surface-sunken); border: 1px solid var(--line); color: var(--ink); }
.inline-error { background: rgba(168,48,43,.06); border: 1px solid rgba(168,48,43,.35); color: var(--danger); }

/* Visible one-line status under a form or button */
.status-line { font-size: 14px; color: var(--muted); margin-top: var(--space-2); min-height: 1.4em; }
.status-line.is-error { color: var(--danger); font-weight: 600; }

/* Inline field error under a .field */
.form-error { color: var(--danger); font-size: var(--fs-sm); font-weight: 600; margin-top: var(--space-1); }

/* Destructive buttons */
.btn-danger {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--danger);
}
.btn-danger:hover, .btn-danger.is-armed {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--on-fill);
}
.btn-danger:hover { transform: none; }

/* Ranking trend chips */
.chip-up   { color: var(--ok); border-color: var(--ok); background: rgba(46,107,79,.08); }
.chip-down { color: var(--clay-dark); border-color: var(--clay); background: rgba(199,91,57,.08); }
.chip-up::before   { content: "\25B2\00A0"; }
.chip-down::before { content: "\25BC\00A0"; }

/* Sticky in-page chip nav */
/* Leave room for the sticky chip bar when jumping to a section (it wraps
   onto more rows on phones). Only pages that have the bar get the offset. */
html:has(.page-chips) { scroll-padding-top: 72px; }
@media (max-width: 640px) { html:has(.page-chips) { scroll-padding-top: 140px; } }
.page-chips {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  margin-bottom: var(--space-4);
  background: var(--cream);
}
.page-chips a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 6px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--card);
  color: var(--ink);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
}
.page-chips a:hover, .page-chips a[aria-current="true"] { border-color: var(--pine); color: var(--pine); }

/* Admin filter rows + list rows */
.admin-filters { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-4); }
.admin-filter {
  min-height: 40px;
  padding: 8px 16px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--card);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  transition: border-color .2s, background .2s, color .2s;
}
.admin-filter:hover { border-color: var(--pine); }
.admin-filter[aria-selected="true"] { background: var(--pine); border-color: var(--pine); color: var(--cream); }

.admin-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
  align-items: start;
}
.admin-row:last-child { border-bottom: none; }
@media (min-width: 720px) {
  .admin-row { grid-template-columns: minmax(0, 2fr) minmax(0, 1.5fr) minmax(0, 1fr); }
}

.save-flag { font-size: var(--fs-xs); font-weight: 600; color: var(--ok); }
.save-flag.is-pending { color: var(--muted); }
.save-flag.is-err { color: var(--danger); }
