/* ============================================================
   Zone Ten AI — stylesheet · DIRECTION A "WARM HUMANIST"
   ------------------------------------------------------------
   Principles, set against what got rejected:
     1. Sentence case. Caps only on small labels.
     2. Warmth comes from ground tints, generous line-height and
        soft edges — not from decoration.
     3. Orange is the action colour. Deepened (--signal-text) whenever
        it carries text; raw only for fills, dots and rules.
     4. Cards breathe on a tinted ground rather than sharing hard edges.
     5. Content is never hidden behind script. No opacity-0 reveals.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* WCAG 2.2 SC 2.4.11 Focus Not Obscured. The header is sticky at
     --header-h, so without this a tab-to-target just off-screen gets
     scrolled to y=0 and sits underneath it. */
  scroll-padding-top: calc(var(--header-h) + 1rem);
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
}
img, video { max-width: 100%; display: block; }
a { color: inherit; }

/* ---------- Focus ---------- */
/* There was no global focus style at all — only two component rules,
   both painting the ring in raw --signal (2.29:1 on white), i.e. less
   visible than the browser default they suppressed. One ink baseline
   for everything, 3px so it survives the 2px offset gap. */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}
/* Ink is invisible on the inverted bands, so the token flips there and
   every ring inside inherits it. */
.band-dark, .site-footer, .on-dark, .tier-featured { --focus: var(--dark-ink); }

/* Visually hidden but exposed to assistive tech. Needed by the markup
   fixes (required-field announcements, form status regions). */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Skip link ---------- */
/* Off-screen by transform, not by `top`. The reduced-motion block sets
   transition:none !important; a top-based slide interrupted mid-way
   could strand the link half over the header. A transform toggle has
   no intermediate state to strand in. z-index clears the sticky
   header's 60. */
.skip-link {
  position: fixed; top: 0; left: 0; z-index: 100;
  transform: translateY(-120%);
  margin: .5rem;
  padding: .8rem 1.2rem;
  background: var(--ink);
  color: var(--bg);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--w-label);
  text-decoration: none;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  transition: transform .15s ease;
}
/* :focus rather than :focus-visible — a skip link is only ever reached
   by keyboard, and it must appear on the very first Tab. The ring is
   inset and orange: an ink ring offset outside an ink box would be
   invisible against the box, and a warm-white one invisible against the
   page. Signal on ink is 7.17:1. */
.skip-link:focus {
  transform: translateY(0);
  outline: 3px solid var(--signal);
  outline-offset: -3px;
}

.container { max-width: var(--grid-max); margin: 0 auto; padding-inline: var(--gutter); }
.section       { padding-block: var(--band); }
.section-tight { padding-block: var(--band-tight); }
.mt-4 { margin-top: 1rem; } .mt-6 { margin-top: 1.7rem; } .mt-7 { margin-top: 2.4rem; }

/* ---------- Type ---------- */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  line-height: 1.14;
  letter-spacing: var(--track-tight);
  margin: 0;
}
h1 { font-size: var(--text-hero); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-lg); letter-spacing: -0.012em; }
/* Emphasis is the deepened orange — readable at any size, unlike the
   raw signal. */
h1 em, h2 em, h3 em { font-style: normal; color: var(--signal-text); }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }
.lead { font-size: var(--text-md); color: var(--muted); max-width: 44ch; }

/* The one place caps still earns its keep */
.eyebrow {
  display: inline-flex; align-items: center; gap: .65em;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--w-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1.3rem;
}
.eyebrow::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--signal); flex: none;
}
.on-dark .eyebrow { color: var(--dark-muted); }

/* ---------- Actions ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .6em;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--w-label);
  text-decoration: none;
  padding: .95em 1.6em;
  border-radius: var(--radius);
  border: 1.5px solid transparent;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.btn-primary { background: var(--signal); color: #1B1512; }
.btn-primary:hover { background: var(--signal-text); color: #fff; }
/* The border is the ONLY thing defining this button, so 1.4.11 applies
   to it. --rule-strong was 1.74:1; --field-border is 3.97:1 on
   --surface, 3.67:1 on --bg. */
.btn-ghost { border-color: var(--field-border); color: var(--ink); }
.btn-ghost:hover { border-color: var(--ink); background: var(--ink); color: var(--bg); }
.btn-lg { padding: 1.05em 1.9em; font-size: var(--text-base); }
.on-dark .btn-ghost { border-color: var(--field-border-dark); color: var(--dark-ink); }
.on-dark .btn-ghost:hover { background: var(--dark-ink); color: var(--dark-bg); border-color: var(--dark-ink); }

.link-arrow {
  text-decoration: none;
  font-weight: var(--w-label);
  font-family: var(--font-display);
  color: var(--signal-text);
  border-bottom: 1.5px solid var(--signal);
  padding-bottom: 1px;
}
.link-arrow::after { content: " →"; }
.link-arrow:hover { border-bottom-color: var(--signal-text); }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease;
}
.site-header.is-scrolled { border-bottom-color: var(--rule); }
/* min-height in rem, shared with the mobile drawer's inset and with
   scroll-padding-top, so all three track text zoom together. */
.header-inner { display: flex; align-items: center; gap: 1.5rem; min-height: var(--header-h); }
.header-logo { display: block; flex: none; }
.header-logo img { height: 23px; width: auto; }

.primary-nav { margin-left: auto; display: flex; align-items: center; gap: 1.8rem; }
.primary-nav a:not(.btn), .nav-drop-toggle {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 500;
  text-decoration: none;
  color: var(--muted);
  background: none; border: 0; padding: 0;
  cursor: pointer;
}
/* padding:0 above gave the desktop nav links a ~24-25px target height.
   That squeaks past 2.5.8 on the spacing exception; padding-block
   removes the argument (≈42px) without changing the visual rhythm,
   since .header-inner's min-height already governs bar height.
   Direct children only — .nav-drop a gets its own padding below. */
.primary-nav > a:not(.btn), .nav-drop-toggle { padding-block: .55rem; }
.primary-nav a:not(.btn):hover, .nav-drop-toggle:hover { color: var(--ink); }
.primary-nav a[aria-current="page"] { color: var(--ink); }
.nav-group { position: relative; }
.nav-group.is-current .nav-drop-toggle { color: var(--ink); }
.caret { font-size: .7em; }

.nav-drop {
  position: absolute; top: calc(100% + 16px); left: -1rem;
  display: none; flex-direction: column;
  min-width: 250px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: .5rem;
  overflow: hidden;
}
/* Scoped to .primary-nav so it outweighs .primary-nav a:not(.btn)'s
   padding:0 — at (0,1,1) this rule was losing to that (0,2,1) selector
   and the dropdown links were rendering with no padding at all, i.e.
   ~24px targets inside a 250px-wide menu. */
.primary-nav .nav-drop a { padding: .7rem .9rem; border-radius: var(--radius); }
.nav-drop a:hover { background: var(--tint); color: var(--ink); }
.nav-group.is-open .nav-drop { display: flex; }

.nav-toggle {
  display: none; margin-left: auto;
  width: 42px; height: 42px;
  /* Border is the only edge this control has — 1.4.11 applies. */
  background: none; border: 1px solid var(--field-border); border-radius: var(--radius);
  flex-direction: column; justify-content: center; align-items: center; gap: 5px;
  cursor: pointer;
}
.nav-toggle .bar { width: 17px; height: 1.5px; background: var(--ink); border-radius: 2px; }

/* ---------- Hero ---------- */
.hero { padding-block: clamp(2.6rem, 6vw, 5rem) clamp(3rem, 7vw, 5.5rem); }
.hero-grid {
  display: grid;
  grid-template-columns: 1.25fr .75fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.hero h1 { margin-bottom: 1.5rem; }
.hero .lead { max-width: 42ch; }
.hero-cta { display: flex; flex-wrap: wrap; gap: .9rem; align-items: center; margin: 2.2rem 0 1.2rem; }
.hero-note { font-size: var(--text-sm); color: var(--faint); max-width: 42ch; }

/* Photography well — the element the rejected build was missing.
   Dashed until real photography exists; swap for an <img> then. */
.photo-well {
  aspect-ratio: 4 / 5;
  border: 1.5px dashed var(--rule-strong);
  border-radius: var(--radius-lg);
  background: var(--tint);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
  gap: .5rem; padding: 1.5rem;
}
.photo-well b {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted);
}
.photo-well span { font-size: var(--text-sm); color: var(--faint); max-width: 26ch; }

/* Approval card — soft, warm, sits on the page rather than boxed in */
.panel {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.panel-head {
  display: flex; align-items: center; gap: .6em;
  padding: .85rem var(--cell-pad);
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted);
}
.status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--signal); flex: none; }
.panel-body { padding: var(--cell-pad); }
.panel-subject { font-family: var(--font-display); font-weight: var(--w-label); margin-bottom: .5rem; }
.panel-draft { color: var(--muted); font-size: var(--text-sm); margin: 0; }
.panel-actions { display: flex; gap: .6rem; padding: 0 var(--cell-pad) var(--cell-pad); }
.panel-approve {
  background: var(--signal); color: #1B1512;
  padding: .6rem 1.1rem; border-radius: var(--radius);
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: var(--w-label);
}
.panel-edit { color: var(--muted); padding: .6rem .6rem; font-size: var(--text-sm); }
.panel-readout {
  display: flex; align-items: baseline; gap: .5em;
  margin-top: 1rem; padding-left: .2rem;
  font-size: var(--text-sm); color: var(--muted);
}
.panel-readout strong {
  font-family: var(--font-display); font-size: var(--text-lg);
  font-weight: var(--w-display); color: var(--ink);
}

/* ---------- Cards on a tinted ground ---------- */
.band-tint { background: var(--tint); }
.cards { display: grid; gap: 1.2rem; }
/* home.html has used `cards cards-2` since it was written; the class
   was never defined, so those two cards stacked single-column at every
   width including desktop. */
.cards-2 { grid-template-columns: repeat(2, 1fr); }
.cards-3 { grid-template-columns: repeat(3, 1fr); }
.cards-4 { grid-template-columns: repeat(4, 1fr); }
.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: var(--cell-pad);
  text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
a.card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--rule-strong); }
.card-label {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted); margin-bottom: .9rem;
}
.card h3 { margin-bottom: .7rem; }
.card p { color: var(--muted); font-size: var(--text-sm); margin: 0; }
.card-big {
  font-family: var(--font-display); font-weight: var(--w-display);
  font-size: var(--text-xl); margin-bottom: .5rem;
}
.card-flag {
  display: inline-block; margin-top: 1.1rem;
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  color: var(--signal-text);
}

/* ---------- Dark statement band ---------- */
.band-dark { background: var(--dark-bg); color: var(--dark-ink); }
.statement {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: var(--text-xl);
  line-height: 1.32;
  letter-spacing: var(--track-tight);
  max-width: 30ch;
  margin: 0;
}
/* On the dark ground the raw signal is legible (6.3:1), so emphasis
   can be colour here rather than a rule. */
.statement .accent { color: var(--signal); }

/* ---------- Numbered task list ---------- */
.task-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 3rem; }
.task-list li {
  display: grid; grid-template-columns: 2.3rem 1fr; gap: .6rem;
  align-items: baseline;
  padding: .95rem 0;
  border-bottom: 1px solid var(--rule);
}
.task-list .idx {
  font-family: var(--font-display); font-weight: var(--w-label);
  font-size: var(--text-sm); color: var(--signal-text);
}

/* ---------- Sector rows ---------- */
/* A <ul> now, so screen readers announce "list, 6 items" — the bare <a>
   stack said nothing about how many sectors there were. */
.sector-rows { border-top: 1px solid var(--rule); list-style: none; margin: 0; padding: 0; }
.sector-row {
  display: grid; grid-template-columns: minmax(0,16rem) 1fr auto;
  gap: 1.2rem; align-items: baseline;
  padding: 1.25rem .6rem;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  border-radius: var(--radius);
  transition: background .14s ease;
}
.sector-row:hover { background: var(--tint); }
.sector-row .name { font-family: var(--font-display); font-weight: var(--w-label); }
.sector-row .hint { color: var(--muted); font-size: var(--text-sm); }
.sector-row .arrow { color: var(--signal-text); }

/* ---------- Video ---------- */
.demo-video {
  /* CLS: the <video> carries no width/height, so with no ratio reserved
     here it painted at the replaced-element default 300x150 and then
     jumped to full width once metadata arrived. The wrapper holds the
     box from first paint. */
  aspect-ratio: 16 / 9;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow);
}
/* The <video> must actually fill the reserved box, or it still paints
   at 300x150 inside a correctly-sized wrapper. */
.demo-video video { width: 100%; height: 100%; object-fit: cover; }
.video-caption {
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  margin-top: .8rem;
  font-size: var(--text-xs);
  color: var(--faint);
}

/* ---------- Split ---------- */
.split { display: grid; grid-template-columns: .9fr 1.1fr; gap: clamp(1.8rem, 5vw, 4.5rem); align-items: start; }
.moat-rows { display: grid; gap: 1.6rem; }
.moat-row { display: grid; grid-template-columns: 2.2rem 1fr; gap: .8rem; }
.moat-row .glyph {
  font-family: var(--font-display); font-weight: var(--w-display);
  color: var(--signal); font-size: var(--text-md);
}
.moat-row h3 { margin-bottom: .5rem; color: var(--dark-ink); font-size: var(--text-md); }
.moat-row p { color: var(--dark-muted); font-size: var(--text-sm); margin: 0; }

/* ---------- Steps ---------- */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; }
.step-kicker {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--signal-text); margin-bottom: .7rem;
}

/* ---------- Final CTA ---------- */
.cta-final { background: var(--tint); text-align: center; }
.cta-final h2 { max-width: 20ch; margin: 0 auto 1rem; }
.cta-final .lead { margin: 0 auto; }
.cta-final .btn { margin-top: 2rem; }
.sig {
  margin-top: 2.6rem;
  font-family: var(--font-display);
  font-size: var(--text-sm); font-weight: var(--w-label);
  color: var(--faint);
}

/* ---------- Footer ---------- */
.site-footer { background: var(--dark-bg); color: var(--dark-ink); padding-block: var(--band-tight); }
.footer-top {
  display: grid; grid-template-columns: 1.5fr repeat(3, 1fr); gap: 2rem;
  padding-bottom: 2.4rem; border-bottom: 1px solid var(--dark-rule);
}
.footer-brand img { height: 16px; width: auto; margin-bottom: 1rem; }
.footer-brand .tag { font-family: var(--font-display); font-size: var(--text-sm); color: var(--dark-muted); }
.footer-col { display: flex; flex-direction: column; gap: .6rem; }
/* Footer link groups are real lists now; drop the markers, keep the stack. */
.footer-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
.col-label {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--dark-muted); margin: 0 0 .4rem;
}
.footer-col a { font-size: var(--text-sm); text-decoration: none; color: var(--dark-ink); }
.footer-col a:hover { color: var(--signal); }
.footer-legal { margin-top: 1.8rem; font-size: var(--text-xs); color: var(--dark-muted); max-width: 62ch; }

/* ---------- Motion ---------- */
/* Content is visible by default and never depends on script. Any
   future reveal must enhance visible content, not create it. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  /* This block used to kill transitions only. `.pulse-dots span` runs
     zt-pdot infinitely for the whole duration of the audit's LLM call
     — an unstoppable auto-playing animation over five seconds, i.e. a
     2.2.2 failure — and the wordmark's bob is literally perpetual.
     Deliberately NOT `animation: none`: .brand-mark .animated-glyph is
     declared opacity:0 and animated to 1, so removing the animation
     strands the wordmark invisible. Collapsing the duration instead
     runs each animation to completion in under a frame, which lands
     every glyph on its final state. */
  *, *::before, *::after {
    transition: none !important;
    animation-duration: .001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Responsive ---------- */
@media (max-width: 1020px) {
  .cards-4 { grid-template-columns: repeat(2, 1fr); }
  .task-list { grid-template-columns: 1fr; gap: 0; }
}
@media (max-width: 900px) {
  .hero-grid, .split { grid-template-columns: 1fr; }
  .photo-well { aspect-ratio: 16 / 10; }
  .cards-3, .steps { grid-template-columns: 1fr; }
  .sector-row { grid-template-columns: 1fr auto; }
  .sector-row .hint { display: none; }
  .footer-top { grid-template-columns: 1fr 1fr; }
}

/* Mobile nav — a real drawer. The live akoai.ai hides every link
   below 820px with no toggle at all; that defect does not come across. */
@media (max-width: 860px) {
  .nav-toggle { display: flex; }
  /* .site-header's backdrop-filter makes the header a containing block
     for fixed-position descendants, so the drawer's inset resolved
     against the 72px header rather than the viewport — it rendered as a
     41px scrolling strip with all seven links overflowing out of it.
     Dropping the filter only while the drawer is open hands the
     containing block back to the viewport. Nothing is lost: the drawer
     is opaque and covers everything the blur would have sampled, and
     the background goes fully opaque to match. Pre-dates the rem
     conversion — it failed identically at 100% and 200% text. */
  .site-header:has(.primary-nav.is-open) {
    backdrop-filter: none;
    background: var(--bg);
  }
  .primary-nav {
    display: none;
    /* Shares --header-h with .header-inner's min-height. Hardcoded 72px
       here desynchronised from the header at 200% text zoom and buried
       the first nav item. */
    position: fixed; inset: var(--header-h) 0 0;
    margin: 0; flex-direction: column; align-items: stretch; gap: 0;
    background: var(--bg);
    border-top: 1px solid var(--rule);
    padding: .5rem 0 2rem;
    overflow-y: auto; z-index: 55;
  }
  .primary-nav.is-open { display: flex; }
  .primary-nav > a:not(.btn), .nav-group > .nav-drop-toggle {
    padding: 1.1rem var(--gutter);
    border-bottom: 1px solid var(--rule-hair);
    text-align: left; width: 100%;
    display: flex; align-items: center; justify-content: space-between;
  }
  .nav-drop {
    position: static; min-width: 0; border: 0; box-shadow: none;
    background: var(--tint); border-radius: 0; padding: 0;
  }
  .primary-nav .nav-drop a { padding: .9rem calc(var(--gutter) + 1rem); border-radius: 0; }
  .primary-nav .btn { margin: 1.4rem var(--gutter) 0; justify-content: center; }
}

@media (max-width: 620px) {
  .cards-4, .cards-3, .cards-2, .footer-top { grid-template-columns: 1fr; }
}

/* ---------- Integration chips ---------- */
/* Category labels rather than brand logos: naming platforms is a claim,
   and the integration list isn't confirmed yet. Swap for real logos once
   it is — that's the version that earns the credibility. */
.chip-row { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .6rem; }
.chip-row li {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  padding: .5rem 1rem;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--w-label);
  color: var(--muted);
}

/* ---------- Founder ---------- */
.founder {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: clamp(1.2rem, 3vw, 2.4rem);
  align-items: center;
  border-top: 1px solid var(--rule);
  padding-top: clamp(1.6rem, 3vw, 2.4rem);
}
.founder-photo {
  aspect-ratio: 1;
  border: 1.5px dashed var(--rule-strong);
  border-radius: 50%;
  background: var(--tint);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: .2rem; text-align: center;
}
.founder-photo b {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted);
}
.founder-photo span { font-size: var(--text-xs); color: var(--faint); }
.founder p { max-width: 60ch; }
.founder strong { font-family: var(--font-display); font-weight: var(--w-display); }

@media (max-width: 620px) {
  .founder { grid-template-columns: 1fr; justify-items: start; }
  .founder-photo { width: 140px; }
}

/* Small print under a card grid (e.g. the GBP note) */
.cell-note { font-size: var(--text-sm); color: var(--muted); max-width: 62ch; }

/* ---------- Wordmark reveal ---------- */
/* Two marks, one shown. The choice is made by a synchronous <head>
   script, so the correct one is painted first time — no swap, no flash.
   Default (no JS, repeat visit, reduced motion) is the static mark. */
.header-logo .mark-animated { display: none; }
.zt-reveal-mark .header-logo .mark-static { display: none; }
.zt-reveal-mark .header-logo .mark-animated { display: block; }

/* ---------- Brand moment ---------- */
/* The mark at size, immediately before the call to action: prepared,
   approved, done — then the ask. Styles are scoped under .brand-mark so
   the inline SVG's rules cannot leak into the rest of the document.
   Animations are paused until the section is scrolled into view, so the
   sequence is seen rather than missed. */
.brand-moment {
  background: var(--tint);
  text-align: center;
  padding-block: clamp(4.5rem, 9vw, 8.5rem);
}
/* The business name, at the scale a business name deserves. Breaks out
   of the standard container — this is the one place on the page the
   mark is the subject rather than a label. */
/* Full-bleed: the mark runs edge to edge, ignoring the page grid. */
.brand-moment .container { max-width: none; padding-inline: clamp(1rem, 3vw, 3rem); }
.brand-mark { max-width: 100%; margin: 0 auto; }
.brand-mark-svg { width: 100%; height: auto; display: block; overflow: visible; }
.brand-strap {
  margin-top: clamp(1.8rem, 3vw, 3rem);
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--w-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
}

.brand-mark .animated-glyph { opacity: 0; animation: zt-reveal .62s cubic-bezier(.2,.8,.2,1) forwards; }
/* Letters land left to right, 180ms apart. Keyed on the glyph ids rather
   than style="animation-delay:…" so the CSP can refuse inline styles. */
.brand-mark #letter-z      { animation-delay:    0ms; }
.brand-mark #letter-o      { animation-delay:  180ms; }
.brand-mark #letter-n-zone { animation-delay:  360ms; }
.brand-mark #letter-e-zone { animation-delay:  540ms; }
.brand-mark #letter-t      { animation-delay:  720ms; }
.brand-mark #letter-e-ten  { animation-delay:  900ms; }
.brand-mark #letter-n-ten  { animation-delay: 1080ms; }
.brand-mark #letter-a      { animation-delay: 1260ms; }
.brand-mark #signal-i      { animation-delay: 1440ms; }
.brand-mark .animated-tick path {
  stroke-dasharray: 65; stroke-dashoffset: 65;
  animation: zt-draw .85s cubic-bezier(.35,.9,.35,1) 2.20s forwards;
}
.brand-mark .animated-tick {
  transform-box: fill-box; transform-origin: 50% 50%;
  animation: zt-confirm .40s cubic-bezier(.34,1.5,.5,1) 2.98s both;
}
/* The dot lands, then bobs. Requested by Mr Lavelle; note this is a
   perpetual motion, which the brand doc's motion rules argue against. */
.brand-mark .animated-dot {
  transform-box: fill-box; transform-origin: center; transform: scale(0);
  animation: zt-pulse .52s cubic-bezier(.2,1.7,.4,1) 1.75s forwards,
             zt-bob 1.5s ease-in-out 2.27s infinite;
}
/* Paused until scrolled into view */
.brand-mark .animated-glyph,
.brand-mark .animated-tick,
.brand-mark .animated-tick path,
.brand-mark .animated-dot { animation-play-state: paused; }
.brand-mark.is-playing .animated-glyph,
.brand-mark.is-playing .animated-tick,
.brand-mark.is-playing .animated-tick path,
.brand-mark.is-playing .animated-dot { animation-play-state: running; }

/* Keyframes for the inline mark. These live in the SVG's own <style>
   for the <img>-loaded copies, but that block is stripped when the SVG
   is inlined — so they must be declared here or every glyph stays at
   opacity 0. */
@keyframes zt-reveal  { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
@keyframes zt-draw    { to { stroke-dashoffset: 0; } }
@keyframes zt-pulse   { to { transform: scale(1); } }
@keyframes zt-confirm { 0% { transform: scale(1); } 45% { transform: scale(1.16); } 100% { transform: scale(1); } }
@keyframes zt-bob {
  0%, 100% { transform: translateY(0) scale(1); }
  50%      { transform: translateY(-20px) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .brand-mark .animated-glyph,
  .brand-mark .animated-tick,
  .brand-mark .animated-tick path,
  .brand-mark .animated-dot {
    /* Belt and braces over the global collapse above. !important is
       load-bearing here: these four selectors also carry
       animation-play-state:paused until .is-playing is added, and a
       paused animation holds its 0% frame — which for .animated-glyph
       is opacity:0. Killing animation-name outright is the only way the
       declared opacity:1 below can take effect. */
    animation: none !important;
    animation-play-state: running !important;
    opacity: 1 !important;
    stroke-dashoffset: 0 !important;
    transform: none !important;
  }
}

/* Opener variant: the mark sits above the hero, so it needs less
   vertical padding than it did as a closing moment, and it shares the
   page background rather than sitting on a tint band. */
.brand-moment-top {
  background: var(--bg);
  padding-block: clamp(1.6rem, 3.5vw, 3.2rem) clamp(0.5rem, 1.5vw, 1.4rem);
}
.brand-moment-top .brand-strap { margin-top: clamp(1rem, 2vw, 1.6rem); }

/* Header mark fades out while the full-bleed opener is on screen, so the
   wordmark never appears twice at once. Nav stays put throughout. */
.site-header .header-logo { transition: opacity .25s ease, visibility .25s ease; }
.site-header.mark-hidden .header-logo { opacity: 0; visibility: hidden; }

/* ============================================================
   INNER PAGES — Direction A components for the 11 templates that
   still carried pre-A markup. Same tokens, same language.
   ============================================================ */

/* ---------- Page head (inner-page hero) ---------- */
.page-head {
  padding-block: clamp(2.4rem, 5.5vw, 4.6rem) clamp(1.6rem, 3.5vw, 3rem);
  border-bottom: 1px solid var(--rule);
}
.page-head h1 { font-size: var(--text-3xl); max-width: 22ch; margin-bottom: 1.1rem; }
.page-head .lead { max-width: 52ch; }
.page-head a { color: var(--signal-text); }

.kicker {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--signal-text); margin: 0 0 .6rem;
}
.strap { color: var(--muted); font-size: var(--text-sm); }
.center-note { text-align: left; color: var(--muted); font-size: var(--text-sm); max-width: 62ch; }
.big { font-family: var(--font-display); font-weight: var(--w-display); font-size: var(--text-xl); }

/* ---------- FAQ ---------- */
.faq { max-width: 780px; }
.faq details {
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--surface);
  margin-bottom: .8rem;
  overflow: hidden;
}
.faq summary {
  cursor: pointer; list-style: none;
  padding: 1.1rem var(--cell-pad);
  font-family: var(--font-display); font-weight: var(--w-label);
  position: relative; padding-right: 3rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; position: absolute; right: 1.2rem; top: 50%;
  transform: translateY(-50%);
  color: var(--signal-text); font-size: 1.25em; font-weight: 400;
}
.faq details[open] summary::after { content: "–"; }
.faq .ans {
  padding: 0 var(--cell-pad) 1.2rem;
  color: var(--muted); font-size: var(--text-sm);
}
.ans a { color: var(--signal-text); }

/* ---------- Prose / About ---------- */
.prose { max-width: 66ch; }
.prose p { margin-bottom: 1.1em; color: var(--ink); }
.split-head h2 { max-width: 16ch; }
.on-light .glyph { color: var(--signal-text); }
.on-light .moat-row h3 { color: var(--ink); }
.on-light .moat-row p { color: var(--muted); }

/* ---------- Pricing tables ---------- */
.sla-scroll { overflow-x: auto; }
table.sla {
  width: 100%; border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  overflow: hidden; font-size: var(--text-sm);
}
table.sla th, table.sla td {
  text-align: left; padding: .9rem 1.1rem;
  border-bottom: 1px solid var(--rule-hair);
}
table.sla thead th {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted); background: var(--tint);
}
table.sla tbody th[scope="row"] { font-family: var(--font-display); font-weight: var(--w-label); }
table.sla tr:last-child td, table.sla tr:last-child th { border-bottom: 0; }
table.sla .hero-col { background: var(--signal-wash); }
.sla-note { color: var(--muted); font-size: var(--text-sm); max-width: 70ch; margin-top: 1.1rem; }
.sla-note strong { color: var(--ink); }
.price { font-variant-numeric: tabular-nums; }

/* ---------- Tier cards (service pages) ---------- */
.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; align-items: stretch; }
.tier {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: var(--cell-pad);
  display: flex; flex-direction: column;
}
/* "Recommended" was signalled only by an orange border at 2.29:1 on
   --surface / 2.12:1 on --bg. The inset ink hairline gives the edge a
   16.45:1 component, so the tier is still visibly picked out without
   relying on the orange being resolvable. (Note: no template currently
   uses .hero-tier — the pricing page's recommended tier is
   .tier-featured, which is already a solid dark card and passes.) */
.tier.hero-tier {
  border: 2px solid var(--signal);
  box-shadow: inset 0 0 0 1px var(--ink), var(--shadow);
}
.tier-tag {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--signal-text); margin-bottom: .7rem;
}
.tier h3 { margin-bottom: .3rem; }
.tier .price {
  font-family: var(--font-display); font-weight: var(--w-display);
  font-size: var(--text-xl); margin: .4rem 0 1rem;
}
.tier .price small { font-size: var(--text-xs); color: var(--muted); font-weight: var(--w-body); }
.tier ul { list-style: none; margin: 0 0 1.2rem; padding: 0; }
.tier li {
  padding: .5rem 0 .5rem 1.5rem; position: relative;
  font-size: var(--text-sm); color: var(--muted);
  border-bottom: 1px solid var(--rule-hair);
}
.tier li::before { content: "✓"; position: absolute; left: 0; color: var(--signal-text); }
.tier .btn { margin-top: auto; justify-content: center; }
.tier-note { font-size: var(--text-xs); color: var(--faint); margin-top: .8rem; }
/* opacity:.45 put the ghost label at #9C9A98 = 2.80:1 on --surface
   (2.27:1 once it inherited .tier-soon's opacity too). Real colours
   instead: --disabled-ink is 5.28:1 on --surface and 4.55:1 on --tint,
   the --tint fill and not-allowed cursor carry the "inert" reading that
   the opacity used to. */
.btn-disabled {
  opacity: 1;
  pointer-events: none;
  cursor: not-allowed;
  color: var(--disabled-ink);
  background: var(--tint);
  border: 1.5px solid var(--field-border);
}

/* ---------- Spec key/value rows (service pages) ---------- */
.kv { display: grid; grid-template-columns: minmax(0,14rem) 1fr; gap: .4rem 1.6rem; }
.k { font-family: var(--font-display); font-weight: var(--w-label); font-size: var(--text-sm); padding: .6rem 0; border-bottom: 1px solid var(--rule-hair); }
.v { color: var(--muted); font-size: var(--text-sm); padding: .6rem 0; border-bottom: 1px solid var(--rule-hair); }

/* ---------- Numbered rail (how-it-works / getting started) ---------- */
.steps-rail, .steps-flow { display: grid; gap: 1.1rem; margin-top: 2rem; }
.rail-step {
  display: grid; grid-template-columns: minmax(3.4rem, max-content) 1fr;
  gap: .2rem 1rem;
  background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  padding: var(--cell-pad);
}
.rail-step .rail-num { grid-row: 1 / span 3; }
.rail-step > h3, .rail-step > p { grid-column: 2; }
/* step-block is a plain card: kicker, title, text stacked — NOT the
   two-column rail. Sharing the rail grid put paragraphs in the narrow
   label column (one word per line). */
.step-block {
  background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  padding: var(--cell-pad);
}
.rail-num {
  font-family: var(--font-display); font-weight: var(--w-display);
  font-size: var(--text-lg); color: var(--signal-text);
}
.rail-step h3, .step-block h3 { margin-bottom: .4rem; font-size: var(--text-md); }
.rail-step p, .step-block p { color: var(--muted); font-size: var(--text-sm); margin: 0; }
.cols-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.2rem; }

/* ---------- Sector panels ---------- */
.sector-panel {
  background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  padding: var(--cell-pad); margin-bottom: 1.2rem;
}
.sector-panel h2, .sector-panel h3 { margin-bottom: .6rem; }
.panel-price { font-family: var(--font-display); font-weight: var(--w-label); }
.from { color: var(--muted); font-size: var(--text-sm); }

/* ---------- Contact ---------- */
/* The two-column rule this class was named for was never written — only the
   .lead width constraint existed, so the panel and copy stacked. */
.contact-hero {
  display: grid;
  grid-template-columns: 1.1fr .9fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
.contact-hero .lead { max-width: 46ch; }
.contact-panel {
  background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  padding: var(--cell-pad); max-width: 560px;
}
.contact-panel .label {
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: var(--w-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted); margin: 1rem 0 .2rem;
}
.contact-panel .label:first-child { margin-top: 0; }
.contact-panel .value { font-size: var(--text-md); }
.contact-panel .value a { color: var(--signal-text); text-decoration: none; }
.divider { border: 0; border-top: 1px solid var(--rule); margin: 1.2rem 0; }

/* ---------- Audit form ---------- */
.audit-layout { display: grid; grid-template-columns: 1.1fr .9fr; gap: clamp(1.8rem,4vw,3.5rem); align-items: start; }
.audit-aside {
  background: var(--tint);
  border-radius: var(--radius-lg); padding: var(--cell-pad);
  /* Was a hardcoded 96px against the header's hardcoded 72px. Same
     desync at 200% text zoom as the mobile drawer. */
  position: sticky; top: calc(var(--header-h) + 1.5rem);
}
.aside-list { list-style: none; margin: 1rem 0 0; padding: 0; }
.aside-list li { padding: .5rem 0 .5rem 1.6rem; position: relative; font-size: var(--text-sm); color: var(--muted); }
.aside-list li::before { content: "✓"; position: absolute; left: 0; color: var(--signal-text); }
.field { margin-bottom: 1.2rem; }
/* :not(.chip) — the multiselect pills are labels too, and a blanket
   display:block here collapsed their flex layout and tick box. */
.field label:not(.chip) {
  display: block;
  font-family: var(--font-display); font-weight: var(--w-label);
  font-size: var(--text-sm); margin-bottom: .4rem;
}
.field .req { color: var(--signal-text); }
.field input, .field textarea, .field select {
  width: 100%; padding: .8rem 1rem;
  font: inherit; color: var(--ink);
  background: var(--surface);
  /* 1.4.11: the box outline is the only thing showing where the field
     is. --rule-strong was 1.74:1 on --surface. */
  border: 1px solid var(--field-border); border-radius: var(--radius);
}
/* Was `outline: 2px solid var(--signal)` — 2.29:1 on --surface, i.e.
   less visible than the UA ring it suppressed. Ink at 3px/2px offset. */
.field input:focus-visible,
.field textarea:focus-visible,
.field select:focus-visible {
  outline: 3px solid var(--focus); outline-offset: 2px; border-color: var(--ink);
}
.form-note { font-size: var(--text-xs); color: var(--faint); }

/* ---------- Inline validation ---------- */
/* Replaces the alert(). --error is 6.54:1 on --surface, 6.04:1 on --bg. */
.field-error {
  display: block;
  margin-top: .35rem;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--w-label);
  color: var(--error);
}
.field-error:empty { display: none; }
/* Colour is never the sole indicator: the error text itself names the
   problem, and the border thickens so the state survives greyscale. */
.field [aria-invalid="true"] {
  border-color: var(--error);
  border-width: 2px;
  background: var(--surface);
}
.field [aria-invalid="true"]:focus-visible { border-color: var(--error); }
.chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.chip {
  border: 1px solid var(--field-border); border-radius: 999px;
  padding: .55rem 1.1rem; cursor: pointer;
  font-size: var(--text-sm); background: var(--surface);
  display: inline-flex; align-items: center; gap: .5rem;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
/* Native box hidden; the pill itself is the control. Keeps it
   keyboard-reachable and screen-reader correct. */
.chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.chip::before {
  content: ""; width: 15px; height: 15px; flex: none;
  /* The tick box has no fill when unchecked — the border IS the
     control. --rule-strong was 1.74:1 on --surface. */
  border: 1.5px solid var(--field-border); border-radius: 4px;
  transition: background .15s ease, border-color .15s ease;
}
/* Checked state was signalled ONLY by the orange fill at 2.29:1 on
   --surface. The ink edge carries the state independently of the
   orange: 16.45:1 against --surface, 7.17:1 against the orange fill
   itself, so the box reads as checked in greyscale and for anyone who
   can't resolve the orange. */
.chip.on::before, .chip:has(input:checked)::before {
  background: var(--signal); border-color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--surface);
}
/* Ink pill edge too, so the state is legible from across the row and
   not only from the 15px box. .chip.on already inverts to a solid ink
   pill via the JS path; this covers the no-JS :checked path. */
.chip:has(input:checked) { border-color: var(--ink); }
/* Ring was --signal at 2.29:1 — weaker than the default it replaced. */
.chip:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
.chip:hover { border-color: var(--ink); }
.chip.on, .chip[aria-pressed="true"] { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.btn-ink { background: var(--ink); color: var(--bg); }
.btn-ink:hover { background: var(--signal); color: #1B1512; }
.result { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-lg); padding: var(--cell-pad); }
/* Empty until the audit returns — an empty bordered box read as a broken panel */
.result:empty { display: none; }
.result-actions { display: flex; gap: .8rem; margin-top: 1.4rem; flex-wrap: wrap; }
/* Audit loading state — hidden until the form submits (JS adds .show) */
#spinner.spinner { display: none; text-align: center; padding: 2rem 0; color: var(--muted); }
#spinner.spinner.show { display: block; }
.pulse-dots { display: flex; gap: .45rem; justify-content: center; margin-bottom: .9rem; }
.pulse-dots span {
  width: 9px; height: 9px; border-radius: 50%; background: var(--signal);
  animation: zt-pdot 1.1s ease-in-out infinite;
}
.pulse-dots span:nth-child(2) { animation-delay: .18s; }
.pulse-dots span:nth-child(3) { animation-delay: .36s; }
@keyframes zt-pdot { 0%,100% { opacity:.35; transform:translateY(0); } 50% { opacity:1; transform:translateY(-5px); } }

/* Retired draft chips — pricing is presented as launch pricing */
.draft-flag { display: none; }

/* ---------- Founder monogram (replaces headshot placeholder) ---------- */
/* Brand mark rather than initials — the block is about the company
   being small and reachable, not about an individual. */
.founder-photo.monogram {
  border: 1.5px solid var(--rule-strong);
  background: var(--surface);
  padding: 1.9rem;
}
.founder-photo.monogram img { width: 100%; height: auto; display: block; }

/* ---------- Honest-numbers band ---------- */
.maths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; align-items: stretch; }
.maths .card p:first-child {
  font-family: var(--font-display); font-weight: var(--w-display);
  font-size: var(--text-2xl); margin-bottom: .3rem; color: var(--ink);
}
.maths .card p:last-child { color: var(--muted); font-size: var(--text-sm); margin: 0; }
.maths-note { font-size: var(--text-xs); color: var(--faint); margin-top: 1rem; max-width: 62ch; }

@media (max-width: 900px) {
  .tiers, .cols-4, .maths { grid-template-columns: 1fr; }
  .audit-layout { grid-template-columns: 1fr; }
  .audit-aside { position: static; }
  .contact-hero { grid-template-columns: 1fr; }
  .kv { grid-template-columns: 1fr; }
  .kv .k { border-bottom: 0; padding-bottom: 0; }
}

/* Pricing page tier grid + featured/soon variants */
.tier-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; align-items: stretch; }
.tier-featured {
  background: var(--dark-bg); border-color: var(--dark-bg);
  box-shadow: var(--shadow);
}
.tier-featured .tier-tag { color: var(--signal); }
.tier-featured h3, .tier-featured .price, .tier-featured h2 { color: var(--dark-ink); }
.tier-featured li { color: var(--dark-muted); border-bottom-color: var(--dark-rule); }
.tier-featured .tier-note { color: var(--dark-muted); }
/* A bare description <p> in a tier (private-ai) inherits body ink, which
   is invisible on this card's dark ground. .price/.tier-tag keep their own
   higher-specificity colours. */
.tier-featured p { color: var(--dark-muted); }
/* opacity:.82 dimmed every descendant: --muted fell to an effective
   #857C77 = 4.02:1 against the composited card, and it compounded with
   .btn-disabled's own opacity. Recessing the card with the tint ground
   reads as "not yet" just as clearly and keeps all text at full
   strength — on --tint, --muted is 5.33:1 and --faint 5.00:1. */
.tier-soon { background: var(--tint); }
.tier-soon .tier-tag { color: var(--muted); }
@media (max-width: 900px) { .tier-grid { grid-template-columns: 1fr; } }

/* Proof strip (service pages) — three cards, matching the home strip */
.proof-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; }
.proof-item {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius-lg); padding: var(--cell-pad);
}
.proof-item .lbl { color: var(--muted); font-size: var(--text-sm); margin-top: .4rem; }
@media (max-width: 900px) { .proof-strip { grid-template-columns: 1fr; } }

/* Tier spec pairs: "Channels: Website", not "ChannelsWebsite" */
.tier .k::after { content: ":"; }
.tier .k { margin-right: .45em; }

/* ---------- Live hero demo ---------- */
.live-demo .panel-draft { min-height: 5.6em; }
.live-demo #ldStatus { transition: color .2s ease; }
.live-demo.is-sent .panel-head { color: var(--signal-text); }
.live-demo.is-sent .panel-approve { background: var(--tint-deep); color: var(--muted); }
.panel-approve { transition: transform .18s ease, background .25s ease, color .25s ease; }
.panel-approve.pressed { transform: scale(.94); background: var(--signal-text); color: #fff; }

/* ---------- Task list: the week, ticked off ---------- */
.task-list li .idx { transition: color .3s ease; }
.task-list li::after {
  content: "✓"; grid-column: 2; justify-self: end;
  color: var(--signal-text);
  opacity: 0; transform: scale(.4);
  transition: opacity .35s ease, transform .35s cubic-bezier(.2,1.6,.4,1);
  margin-top: -1.55em; font-weight: 700;
}
.task-list li.is-done::after { opacity: 1; transform: scale(1); }
@media (prefers-reduced-motion: reduce) { .task-list li::after { opacity: 1; transform: none; } }

/* With the menu open, always show the header mark (opener may be behind the drawer) */
.site-header:has(.primary-nav.is-open) .header-logo { opacity: 1; visibility: visible; }

/* Legal/doc pages: H2 sections at a sensible size (they were H3s) */
.prose .doc-h { font-size: var(--text-md); margin-top: 2rem; margin-bottom: .5rem; }
.prose .doc-h:first-child { margin-top: 0; }
.tier-sub { font-size: var(--text-sm); color: var(--muted); margin: -.6rem 0 1rem; }
.tier-featured .tier-sub { color: var(--dark-muted); }

/* Small layout utilities. These replace style="…" attributes so the
   Content-Security-Policy can refuse inline styles outright. */
.pt-0     { padding-top: 0; }
.w-full   { width: 100%; }
.h1-tight { font-size: var(--text-2xl); }

/* Several card grids sat as h3 directly under the h1, skipping a level.
   They are real sections, so they became h2 — this keeps the h3 look.
   Matches the h3 rule exactly; change both together. */
.as-h3 { font-size: var(--text-lg); letter-spacing: -0.012em; }

/* The audit's h1 moved out of <aside> — it belongs to the page, not to a
   complementary landmark. */
.audit-head { margin-bottom: clamp(1.6rem, 3vw, 2.4rem); }

/* The multiselect is a fieldset now: a <label for> pointed at an id that
   was never rendered, so the question itself was never announced. */
fieldset.field { border: 0; margin: 0 0 1.2rem; padding: 0; min-inline-size: 0; }
fieldset.field legend {
  /* float, not display:block — legends ignore display:block in several
     engines. Styling matches .field label:not(.chip) exactly. */
  float: left; width: 100%; padding: 0;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--w-label);
  margin-bottom: .4rem;
}
fieldset.field legend + .chips { clear: both; }
/* The generic [aria-invalid] rule only repaints a border, and the chips
   group has none — so its error state needs its own treatment. */
.chips[aria-invalid="true"] {
  outline: 2px solid var(--error);
  outline-offset: 6px;
  border-radius: var(--radius);
}
