/* ==========================================================================
   Crux V6 Control Tower layer
   ==========================================================================
   Loaded last. This is the V6 evolution of the V5 "Blueprint After Dark"
   system. It does not replace the brand: navy, blue, yellow, Bebas Neue,
   IBM Plex Mono, DM Sans and the blueprint grid are all inherited unchanged
   from tokens.css.

   What it adds is a point of view.

   1. A VALUE ARC. In V5 the light/dark alternation carried no meaning: paper,
      paper, navy, card, navy, paper, card... The visitor got no sense of
      travelling anywhere. Here the page darkens monotonically from the yard
      to the tower, so the surface itself tracks chaos -> visibility ->
      control -> confidence -> trust -> action. The page settles as you read.

   2. THREE TYPE VOICES WITH REAL JOBS. V5 let DM Sans do everything and
      barely used Bebas at all. Here:
        Bebas Neue    -> structure. Stencilled markers, stage indices, the
                         rail. The lettering on a drawing.
        DM Sans       -> prose and headlines. What a person says.
        IBM Plex Mono -> the system's voice. Amounts, statuses, timestamps,
                         field labels. Nothing a human wrote.
      A reader can tell who is speaking without reading a word.

   3. THE TOWER RAIL. A hairline spine down the left edge carrying the stage
      the visitor is in. Not navigation and not decoration: it is the Control
      Tower made structural, and it is the one place this page spends its
      boldness. Everything else is quieter than V5.
   ========================================================================== */

:root {
  /* ---- Value arc. Brand hues unchanged; these are stops along the descent. */
  --yard:      #e9e5d9;   /* chaos. dust, paper, daylight on a site */
  --yard-line: #d6d1c2;
  --tower-3:   #f4f2ec;   /* paper, inherited */
  --tower-4:   #ffffff;   /* the cleanest surface. resolution, not chaos */
  --white-line: #e8e6df;
  --tower-2:   #1a2660;   /* navy-900, inherited. the tower */
  --tower-1:   #131c4a;
  --tower-0:   #0b1233;   /* deepest. the tower at night */

  /* ---- Instrument colours. Signal is the locked yellow. */
  --signal:    #FFDA00;
  --settled:   #00c853;
  --waiting:   #FFB300;

  /* ---- Rail */
  --rail-w:    4.75rem;

  /* ---- Rhythm. One scale, used everywhere, so sections stop improvising. */
  --bay:       clamp(4.5rem, 8vw, 9rem);   /* between stages */
  --bay-tight: clamp(2.5rem, 4vw, 4rem);   /* within a stage */
}

/* ==========================================================================
   1. STAGE SURFACES: the value arc
   ========================================================================== */

.home .stage { padding-block: var(--bay); position: relative; }

.stage--yard    { background: var(--yard); color: var(--ink); }
.stage--paper   { background: var(--tower-3); color: var(--ink); }
.stage--white   { background: var(--tower-4); color: var(--ink); }
.stage--tower-2 { background: var(--tower-2); color: var(--on-dark); }
.stage--tower-1 { background: var(--tower-1); color: var(--on-dark); }
.stage--tower-0 { background: var(--tower-0); color: var(--on-dark); }

/* --------------------------------------------------------------------------
   THE SECTION RHYTHM

   This page used to run one way only: cream, paper, paper, then navy getting
   progressively darker through three steps to the close. Read end to end that
   is a descent with no relief in it, and after the boundary section the page
   never returns to daylight.

   V5 alternated. It opened light, dropped to navy for a claim, came back up to
   white, went down again, and returned to light for the long middle before
   closing dark. The contrast is what made each navy section feel like a
   deliberate moment rather than a stage of a fade.

   The rhythm now uses three surfaces and returns to light after every navy
   section except the close:

     hero            navy    the Control Tower, the page's identity
     01 The Yard     cream   content opens light
     02 Line of Sight white   the connected path, on the cleanest surface
     03 Proof        cream
     04 The Boundary navy    the tower moment: Crux against QuickBooks
     05 Every Seat   white   back to daylight
     06 Your Numbers navy    the instrument, where the yellow figures need dark
     close           navy

   Only two surface assignments changed in the markup. The Control Tower story
   is intact: the hero, the boundary, the estimator and the close are still the
   dark spine, they just no longer arrive by fading. */

/* --------------------------------------------------------------------------
   The surface ink contract.

   Reordering the page moved components across the light/dark line. The V5
   role selector was authored against paper and now sits inside the tower; the
   V5 evaluation grid was authored against a navy band and now sits on paper.
   Both went unreadable, because each hard-coded the ink for the surface it
   used to live on.

   The fix is a contract rather than a pile of overrides: a stage redefines the
   ink tokens of the OPPOSITE polarity to its own. A dark stage answers
   --ink/--ink-body/--ink-muted with light values; a light stage answers
   --on-dark with dark ones. Any component can now be moved between stages and
   stay legible without being rewritten, which is the point of having tokens.

   Surface tokens (--card, --paper-2) are deliberately NOT remapped. Cards are
   physical objects on this page: the light worksheet inside the dark demo
   frame, the two light panels either side of the QuickBooks boundary. Those
   read correctly precisely because they stay light on a dark stage.
   -------------------------------------------------------------------------- */

.stage--tower-2,
.stage--tower-1,
.stage--tower-0,
.close-tower {
  --ink:         #ffffff;
  --ink-body:    rgba(255, 255, 255, 0.82);
  --ink-muted:   rgba(255, 255, 255, 0.64);
  --rule:        rgba(255, 255, 255, 0.14);
  --rule-strong: rgba(255, 255, 255, 0.22);
  --blue:        #93a4e8;   /* the brand blue lifted to carry on navy */
}

.stage--yard,
.stage--paper,
.stage--white {
  --on-dark:        var(--ink);
  --on-dark-muted:  var(--ink-body);
  --on-dark-faint:  var(--ink-muted);
  --line-dark:      var(--rule);
}

/* --------------------------------------------------------------------------
   Objects override stages.

   A stage sets the ink for text printed directly on it. But several components
   lay their own opaque surface down first: the demo's navy instrument frame
   sits on a paper stage, and the light worksheet cards sit inside that frame,
   two polarity flips deep. Inheriting the stage's ink through those makes text
   the same colour as the card underneath it.

   So the contract is two-sided and keyed to the surface an element PAINTS, not
   the stage it happens to land on. Anything that paints dark takes .on-dark
   ink; anything that paints light takes .on-light ink; nesting resolves
   naturally because each object re-declares for its own children. New
   components join by being added to the right list, and the page can be
   re-sequenced again without a single component being rewritten.
   -------------------------------------------------------------------------- */

/* Paints dark. */
.demo__frame,
.system__cell {
  --ink:            #ffffff;
  --ink-body:       rgba(255, 255, 255, 0.82);
  --ink-muted:      rgba(255, 255, 255, 0.64);
  --rule:           rgba(255, 255, 255, 0.14);
  --rule-strong:    rgba(255, 255, 255, 0.22);
  --blue:           #93a4e8;
  --on-dark:        #ffffff;
  --on-dark-muted:  rgba(255, 255, 255, 0.82);
  --on-dark-faint:  rgba(255, 255, 255, 0.64);
  --line-dark:      rgba(255, 255, 255, 0.14);
}

/* Paints light. */
.demo__queue, .demo__record, .demo__bacard, .demo__bnode, .demo__levels,
.demo__step, .qbflow__side, .qb__side, .compare__col, .shift__panel,
.team__card, .ba, .lane, .segbar, .shot {
  --ink:            #1a2660;
  --ink-body:       #3b426a;
  --ink-muted:      #5c6485;
  --rule:           #ddd9cc;
  --rule-strong:    #c7c2b1;
  --blue:           #34469d;
  --on-dark:        #1a2660;
  --on-dark-muted:  #3b426a;
  --on-dark-faint:  #5c6485;
  --line-dark:      #ddd9cc;
  color: var(--ink);
}

/* The selected role tab is a light chip on a dark stage: same rule, one
   property, because the tab has no block of its own to re-declare against. */
.stage--tower-2 .roles__tab[aria-selected="true"],
.stage--tower-1 .roles__tab[aria-selected="true"],
.stage--tower-0 .roles__tab[aria-selected="true"] { color: var(--navy); }

/* The seam between a light stage and the first dark one is the moment the
   page enters the tower. Mark it once, with the signal colour, and never
   again: a rule that appears everywhere stops meaning anything. */
.stage--threshold { border-top: 2px solid var(--signal); }

/* The blueprint grid that used to tile these stages was removed in the final
   production pass. What carried the arc was never the squares: it was the
   surface tone stepping from yard to paper to white to tower navy, and the
   stencilled stage marks. Those stay. ::before on the stages is now free, and
   polish.css uses it for the graded seam between one tone and the next. */
.stage > .container { position: relative; z-index: 1; }

/* ==========================================================================
   2. STAGE HEADERS: Bebas as structure
   ========================================================================== */

.stagehead { max-width: 46rem; margin-bottom: var(--bay-tight); }

/* The stencilled marker. Bebas, tracked out, with the stage index in mono so
   the two voices sit side by side and you can hear the difference. */
.stagehead__mark {
  display: flex; align-items: baseline; gap: 0.75rem;
  margin-bottom: 1.1rem;
  border-bottom: 1px solid currentColor;
  padding-bottom: 0.5rem;
  opacity: 0.9;
}
.stagehead__idx {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.08em; opacity: 0.65;
}
.stagehead__label {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.8vw, 1.5rem);
  line-height: 1; letter-spacing: 0.14em; text-transform: uppercase;
}
.stage--yard .stagehead__label,
.stage--paper .stagehead__label,
.stage--white .stagehead__label { color: var(--navy); }
.stage--tower-0 .stagehead__label,
.stage--tower-1 .stagehead__label,
.stage--tower-2 .stagehead__label { color: var(--signal); }

.stagehead__title {
  font-family: var(--font-body); font-weight: 600;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  line-height: 1.08; letter-spacing: -0.02em;
  margin: 0 0 0.9rem;
  max-width: 20ch;
}
.stagehead__lead {
  font-size: clamp(1rem, 1.2vw, 1.1rem); line-height: 1.6;
  opacity: 0.86;
}

/* ==========================================================================
   3. THE TOWER RAIL: the signature
   ==========================================================================
   A hairline spine, fixed to the left edge, showing which stage you are in.
   Desktop only: below 1200px there is no room for a spine that does not
   compete with content, so it becomes a 2px progress hairline at the top.
   ========================================================================== */

/* A solid bezel, not a translucent overlay. Translucency looked accidental
   against the light stages; a constant dark frame reads as the instrument
   housing the view sits inside, which is the whole idea.

   The first draft carried each stage's name in the rail. Set in Bebas at a
   readable size, "THE BOUNDARY" is wider than any spine narrow enough to sit
   beside content, so the names overflowed onto the page. Widening the rail to
   fit the longest word would have spent a sixth of the viewport on a legend.

   So the rail is stripped to what an instrument bezel actually shows: six
   graduations and the one you are on. The numbers are not decoration and not
   an arbitrary ordering device. This page IS a sequence, the stage headers
   already announce "01 THE YARD", and the rail is the same counter read from
   the edge of the drawing. Removing the words made the rail read more like an
   instrument, not less. */
.rail {
  position: fixed; left: 0; top: 0; bottom: 0; width: var(--rail-w);
  z-index: 30; pointer-events: none;
  display: none;
  border-right: 1px solid rgba(255,218,0,0.18);
  background: var(--tower-0);
}
@media (min-width: 75rem) {
  .rail { display: flex; flex-direction: column; justify-content: center; }
  .home { padding-left: var(--rail-w); }
  .rail__list { list-style: none; margin: 0; padding: 0; }
}
.rail__item {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.7rem 0 0.7rem 1.15rem; opacity: 0.38;
  transition: opacity var(--motion-base) var(--ease-standard);
}
.rail__tick {
  width: 0.85rem; height: 1px; background: currentColor; flex: 0 0 auto;
  transition: width var(--motion-base) var(--ease-standard),
              background-color var(--motion-base) var(--ease-standard);
}
.rail__idx {
  font-family: var(--font-mono); font-size: 0.66rem; font-weight: 500;
  letter-spacing: 0.1em; color: #fff; font-variant-numeric: tabular-nums;
}
.rail__item.is-here { opacity: 1; }
.rail__item.is-here .rail__tick { background: var(--signal); width: 1.5rem; }
.rail__item.is-here .rail__idx { color: var(--signal); }

/* Small-screen fallback: a progress hairline, not a spine. */
.railbar {
  position: fixed; top: 0; left: 0; right: 0; height: 2px;
  background: transparent; z-index: 30; pointer-events: none;
}
.railbar__fill {
  height: 100%; width: 0; background: var(--signal);
  transition: width var(--motion-base) var(--ease-standard);
}
@media (min-width: 75rem) { .railbar { display: none; } }

/* ==========================================================================
   4. THE HERO: the control tower itself
   ==========================================================================
   V5 opened with a headline beside two product screenshots: the template
   answer, and it asked the visitor to admire software before they had felt
   the problem. This opens on the instrument instead. The panel is the thesis:
   three jobs, their position, one decision waiting.
   ========================================================================== */

.tower {
  background: var(--tower-0); color: var(--on-dark);
  padding-block: clamp(3.5rem, 7vw, 6rem) var(--bay);
  position: relative; overflow: hidden;
}
/* A single soft light over the panel. One light source, like a desk lamp in a
   trailer, rather than an ambient gradient wash. */
.tower::after {
  content: ""; position: absolute; pointer-events: none;
  width: 60rem; height: 40rem; right: -14rem; top: -16rem;
  background: radial-gradient(closest-side, rgba(52,70,157,0.55), transparent 72%);
}
.tower > .container { position: relative; z-index: 1; }

.tower__grid { display: grid; gap: clamp(2.5rem, 4vw, 4rem); align-items: start; }
@media (min-width: 62rem) {
  .tower__grid { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); }
}

.tower__eyebrow {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-family: var(--font-display); font-size: 0.95rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--signal);
  margin-bottom: 1.4rem;
}
.tower__eyebrow::before {
  content: ""; width: 2rem; height: 2px; background: var(--signal);
}
.tower__title {
  font-family: var(--font-body); font-weight: 600;
  font-size: clamp(2.4rem, 5.2vw, 4.1rem);
  line-height: 1.03; letter-spacing: -0.032em;
  margin: 0 0 1.3rem; color: #fff; max-width: 15ch;
}
.tower__lede {
  font-size: clamp(1.02rem, 1.25vw, 1.18rem); line-height: 1.62;
  color: rgba(255,255,255,0.82); max-width: 46ch; margin: 0 0 2rem;
}
.tower__actions { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-bottom: 1.6rem; }
.tower__note {
  font-size: 0.85rem; line-height: 1.55; color: rgba(255,255,255,0.62);
  max-width: 46ch;
}

/* ---- The panel ---------------------------------------------------------- */

.panel {
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(26,38,96,0.92), rgba(11,18,51,0.92));
  box-shadow: 0 30px 70px rgba(0,0,0,0.42);
  overflow: hidden;
}
.panel__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 0.7rem 1rem;
  border-bottom: 1px solid rgba(255,255,255,0.12);
  background: rgba(0,0,0,0.18);
}
.panel__title {
  font-family: var(--font-display); font-size: 0.95rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: #fff;
}
.panel__tag {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: rgba(255,255,255,0.62);
  border: 1px solid rgba(255,255,255,0.22); border-radius: 999px;
  padding: 2px 8px; white-space: nowrap;
}
.panel__body { padding: 0.35rem 0; }

/* Explicit placement on every child. Auto-placement with a spanning row put
   the figure ahead of the job name, which read as though the number was the
   subject. The name is the subject; the number is what it is doing. */
.job {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "name fig" "meta fig" "bar  bar";
  gap: 0.15rem 1.25rem;
  padding: 0.85rem 1rem; align-items: baseline;
  border-bottom: 1px solid rgba(255,255,255,0.07);
}
.job:last-child { border-bottom: 0; }
.job__name { grid-area: name; font-weight: 600; font-size: 0.95rem; color: #fff; }
.job__meta {
  grid-area: meta;
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em;
  color: rgba(255,255,255,0.62);
}
.job__fig {
  grid-area: fig;
  font-family: var(--font-mono); font-size: 0.95rem; color: #fff;
  align-self: center; text-align: right; white-space: nowrap;
}
.job__fig small {
  display: block; font-size: 0.62rem; letter-spacing: 0.05em;
  color: rgba(255,255,255,0.5); margin-top: 2px;
}
.job__fig--over { color: var(--waiting); }

/* Budget bar: the one place a figure becomes a shape. */
.job__bar {
  grid-area: bar; height: 3px; border-radius: 2px;
  background: rgba(255,255,255,0.12); margin-top: 0.55rem; overflow: hidden;
}
.job__bar span {
  display: block; height: 100%; background: var(--blue);
  width: 0; transition: width 1.1s var(--ease-emphasized);
}
.job__bar span.is-over { background: var(--waiting); }

/* The waiting decision. This is the only row that asks for anything. */
.decision {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  padding: 0.9rem 1rem;
  border-top: 1px solid rgba(255,218,0,0.28);
  background: rgba(255,218,0,0.06);
}
.decision__what { display: flex; flex-direction: column; gap: 0.15rem; }
.decision__vendor { font-weight: 600; font-size: 0.9rem; color: #fff; }
.decision__meta {
  font-family: var(--font-mono); font-size: 0.68rem;
  color: rgba(255,255,255,0.62);
}
.decision__status {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--signal);
  border: 1px solid rgba(255,218,0,0.45); border-radius: 999px; padding: 3px 9px;
}
.decision__status.is-done { color: var(--settled); border-color: rgba(0,200,83,0.5); }

/* ---- Load sequence: chaos resolving into order --------------------------
   The page's single orchestrated moment. Rows arrive in order, then the
   budget bars fill. Nothing autoplays afterwards and nothing loops. */
html.js .tower [data-settle] { opacity: 0; transform: translateY(10px); }
html.js .tower [data-settle].is-settled {
  opacity: 1; transform: none;
  transition: opacity 0.5s var(--ease-standard), transform 0.5s var(--ease-standard);
}

@media (prefers-reduced-motion: reduce) {
  html.js .tower [data-settle] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .job__bar span { transition: none !important; }
}

/* ==========================================================================
   5. THE YARD: chaos, made legible
   ==========================================================================
   V5 stated the problem in a tidy four-row register. Tidy is the wrong
   texture for chaos. These sit on the dusty surface, slightly out of
   alignment with each other, the way paper actually accumulates.
   ========================================================================== */

/* ==========================================================================
   6. THE BOUNDARY: control means knowing your edge
   ========================================================================== */

.edge { display: grid; gap: 1px; background: rgba(255,255,255,0.14); border: 1px solid rgba(255,255,255,0.14); border-radius: 10px; overflow: hidden; }
@media (min-width: 56rem) { .edge { grid-template-columns: 1fr auto 1fr; align-items: stretch; } }

.edge__side { background: var(--tower-1); padding: 1.5rem 1.4rem; }
.edge__side--qb { background: rgba(255,255,255,0.04); }
.edge__cap {
  font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.09em;
  text-transform: uppercase; color: rgba(255,255,255,0.55); display: block; margin-bottom: 0.5rem;
}
.edge__name {
  font-family: var(--font-display); font-size: 1.7rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: #fff; margin-bottom: 0.9rem;
}
.edge__side--qb .edge__name { color: var(--signal); }
.edge__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.edge__list li {
  font-size: 0.9rem; color: rgba(255,255,255,0.82);
  padding-left: 1.1rem; position: relative;
}
.edge__list li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 5px; height: 5px; background: var(--signal); border-radius: 50%;
}
.edge__gap {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.5rem; padding: 1.2rem; background: var(--tower-0); min-width: 11rem;
}
.edge__gap-label {
  font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--signal); text-align: center; line-height: 1.5;
}
.edge__gap-rule { width: 1px; flex: 1; min-height: 2rem; background: rgba(255,218,0,0.4); }
@media (max-width: 55.99rem) { .edge__gap-rule { width: 100%; height: 1px; min-height: 0; } }

/* ==========================================================================
   7. CLOSE: action
   ========================================================================== */

.close-tower { background: var(--tower-0); color: #fff; text-align: center; padding-block: var(--bay); position: relative; }
.close-tower__title {
  font-family: var(--font-body); font-weight: 600;
  font-size: clamp(2rem, 4.4vw, 3.4rem); line-height: 1.05; letter-spacing: -0.03em;
  margin: 0 auto 1rem; max-width: 18ch;
}
.close-tower__lead { color: rgba(255,255,255,0.78); max-width: 50ch; margin: 0 auto 2rem; line-height: 1.6; }
.close-tower .actions { justify-content: center; }
.close-tower__reassure {
  display: block; margin-top: 1.2rem;
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.05em;
  color: rgba(255,255,255,0.5);
}

/* ==========================================================================
   8. QUIETING V5
   ==========================================================================
   The evolution is as much about removing noise as adding signal. V5 revealed
   every section header with the same lift; at speed the whole page twitched.
   Here only stage headers move, and less.
   ========================================================================== */

html.js .stage [data-reveal] { transform: translateY(10px); }

/* Inherited components sitting on a dark stage need their light-surface
   assumptions undone. V5 only ever placed them on paper. */
.stage--tower-0 .sec__title,
.stage--tower-1 .sec__title,
.stage--tower-2 .sec__title { color: #fff; }
.stage--tower-0 .sec__lead,
.stage--tower-1 .sec__lead,
.stage--tower-2 .sec__lead { color: rgba(255,255,255,0.82); }

/* Buttons: V5's secondary button was a yellow-tinted outline that competed
   with the primary. On the arc there is one signal colour and it belongs to
   the action you want taken. */
.stage--tower-0 .btn--secondary,
.stage--tower-1 .btn--secondary,
.tower .btn--secondary,
.close-tower .btn--secondary {
  border-color: rgba(255,255,255,0.32); color: #fff; background: transparent;
}
.stage--tower-0 .btn--secondary:hover,
.stage--tower-1 .btn--secondary:hover,
.tower .btn--secondary:hover,
.close-tower .btn--secondary:hover { border-color: #fff; }

/* Focus stays visible against every surface on the arc. */
.tower :focus-visible,
.stage--tower-0 :focus-visible,
.stage--tower-1 :focus-visible,
.stage--tower-2 :focus-visible,
.close-tower :focus-visible {
  outline: 2px solid var(--signal); outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--tower-0);
}

/* --------------------------------------------------------------------------
   Specificity corrections.

   home.css:51 sets `.home h1, .home h2, .home h3` (0,1,1), which outranks a
   single class. Every heading and lede on the arc therefore has to be scoped
   under `.home` to win. Left unscoped, the hero rendered navy-on-navy.
   -------------------------------------------------------------------------- */

.home .tower__title { color: #fff; }
.home .tower__lede { color: rgba(255,255,255,0.84); }
.home .tower__note { color: rgba(255,255,255,0.64); }
.home .close-tower__title { color: #fff; }
.home .close-tower__lead { color: rgba(255,255,255,0.80); }

.home .stage--yard .stagehead__title,
.home .stage--paper .stagehead__title,
.home .stage--white .stagehead__title { color: var(--ink); }
.home .stage--tower-0 .stagehead__title,
.home .stage--tower-1 .stagehead__title,
.home .stage--tower-2 .stagehead__title { color: #fff; }
.home .stage--tower-0 .stagehead__lead,
.home .stage--tower-1 .stagehead__lead,
.home .stage--tower-2 .stagehead__lead { color: rgba(255,255,255,0.82); }
.home .stage--yard .stagehead__lead,
.home .stage--paper .stagehead__lead,
.home .stage--white .stagehead__lead { color: var(--ink-body); }

.home .edge__name { color: #fff; }
.home .edge__side--qb .edge__name { color: var(--signal); }

/* Vertical rhythm inside a stage. */
.bay-tight { margin-top: var(--bay-tight); }

/* ==========================================================================
   9. THE STENCIL: carrying the system to every other page
   ==========================================================================
   V5's `.kicker` was DM Sans, 12px, letterspaced: the same eyebrow every SaaS
   site uses, and it left Bebas Neue almost unused despite being a locked
   brand face. Restyling this one component applies the tower's structural
   voice to all 45 section headers across the platform, capability, and
   pricing pages at once, without touching their markup.

   Bebas is a condensed uppercase face drawn for signage. Set as a stencilled
   marker against a short rule, it reads like the lettering on a drawing
   sheet, which is where this brand's language comes from.
   ========================================================================== */

.home .kicker {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.35vw, 1.2rem);
  font-weight: 400;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.9rem;
  color: var(--blue);
}
.home .kicker::before {
  content: "";
  width: 1.75rem; height: 2px; flex: 0 0 auto;
  background: currentColor;
}
.home .kicker--ondark { color: var(--signal); }

/* Section titles: V5 ran them at up to 72px, which on a page of eight
   sections meant everything shouted. Bringing the ceiling down and tightening
   the tracking makes the hierarchy legible again. */
.home .sec__title {
  font-size: clamp(1.85rem, 3.4vw, 2.85rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  max-width: 22ch;
}
.home .sec__lead { max-width: 58ch; }

/* One rhythm across every page, replacing three improvised paddings. */
.home .sec { padding-block: var(--bay); }

/* --------------------------------------------------------------------------
   The marketing pages (about, solutions, contact, success) came from a
   different V5 shell: no body class, `.section` instead of `.sec`, `.eyebrow`
   instead of `.kicker`. Left alone they would have kept V5's eyebrow while
   every other page moved to the stencil, which is exactly the kind of drift
   that makes a site feel assembled rather than designed. Same treatment,
   different hooks.
   -------------------------------------------------------------------------- */

.eyebrow {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.35vw, 1.2rem);
  font-weight: 400;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.9rem;
  color: var(--blue);
}
.eyebrow::before {
  content: "";
  width: 1.75rem; height: 2px; flex: 0 0 auto;
  background: currentColor;
}
.section--navy .eyebrow,
.section--dark .eyebrow { color: var(--signal); }

.section { padding-block: var(--bay); }
.section--tight { padding-block: var(--bay-tight); }

/* Their hero ran at the same 96px ceiling as the homepage, so a utility page
   announced itself as loudly as the pitch. */
.hero__title {
  font-size: clamp(2.1rem, 4.2vw, 3.2rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
}
.hero__lead { max-width: 54ch; }

@media print {
  .rail, .railbar { display: none !important; }
  .tower, .close-tower, .stage--tower-0, .stage--tower-1, .stage--tower-2 {
    background: #fff !important; color: #000 !important;
  }
}

/* ==========================================================================
   9. THE DEMO FRAME
   ==========================================================================
   The frame used to carry a 24px blueprint grid to make the reserved height
   read as drafting space rather than as a rendering fault. Both halves of
   that problem are gone: the square-pattern graphics were removed site-wide,
   and polish.css moved the activity trail into the left column, which cuts
   the reserved height enough that there is no large void left to explain.
   ========================================================================== */

.home .demo__frame { position: relative; }
.home .demo__frame > * { position: relative; z-index: 1; }

/* ==========================================================================
   10. AA CORRECTIONS FORCED BY THE NEW ARC
   ==========================================================================
   Two are the redesign's own doing and one is inherited.

   --ink-muted was #626a8c, which measured 4.49:1 on --paper-2. That passed by
   rounding and fails outright on the new --yard surface, which is warmer and
   darker than any V5 background. Taken to #5c6485: 4.61:1 on the yard, 4.92:1
   on paper-2, 5.81:1 on white. Still clearly secondary, now actually legible.

   The evaluation grid's yellow indices were authored against a navy band. The
   Proof stage is now paper, where yellow-on-paper is 1.23:1. The yellow keeps
   its structural job as the rule above each item, where it needs no contrast
   ratio; the numeral goes navy.
   ========================================================================== */

body.home, :root { --ink-muted: #5c6485; }

.stage--yard  .evalitem__no,
.stage--paper .evalitem__no,
.stage--white .evalitem__no { color: var(--navy); }

/* The QuickBooks wordmark is set in Intuit's green, which is 2.89:1 on the
   warm --paper-2 panel it inherited from V5. WCAG exempts logotypes, but the
   mark is real text here and a near-miss is worth closing. Rather than alter
   another company's brand colour, the panel behind it goes to plain white:
   3.41:1, with no change to the mark itself. It also reads correctly, since
   this is the one panel on the page that is not Crux. */
.home .qbflow__side--qb,
.home .qb__side--qb,
.home .qbnote { background: #ffffff; }

/* Same reasoning as the evaluation indices: --yellow-deep was picked for a
   yellow numeral on a dark card and reads 1.71:1 on the white pricing cards
   it now sits on. The step numbers go navy; the yellow keeps its structural
   jobs elsewhere on the page. */
.home .getcrux__no { color: var(--navy); }

/* ==========================================================================
   11. STAGE EXITS
   ==========================================================================
   The rebuild left the platform overview reachable only from the masthead.
   A visitor who has just stepped an invoice through the workflow and wants
   the rest of the system had no route out of the page body.

   A stage exit is one sentence at the foot of a stage that names what the
   reader just saw and offers the next depth. It is not a CTA band: the page
   already ends in one, and repeating that pressure mid-journey would undo
   the calm the arc is built for.
   ========================================================================== */

.home .stage-out {
  margin-top: var(--bay-tight);
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule);
  font-size: 1rem; line-height: 1.6; color: var(--ink-body);
}
.home .stage-out a {
  color: inherit; font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--signal);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}
.home .stage-out a:hover { text-decoration-thickness: 3px; }

/* ==========================================================================
   12. THE ONE DECISION IN THE HERO
   ==========================================================================
   V5 put a small "Approve invoice" toggle in a card beside the hero, where it
   read as a widget demonstrating that something could be clicked. The panel
   makes it the point instead: the row already says an invoice is waiting on
   you, so the control belongs on that row, and approving moves the budget
   bar of the job the invoice is coded to.

   That single gesture is the argument of the whole page in two seconds:
   a decision made here changes what the numbers say, while the work is still
   moving. It is the page's only interactive claim above the fold, it never
   autoplays, and without JS the row renders a complete, readable state.
   ========================================================================== */

.home .decision__act {
  display: none;
  font-family: var(--font-body); font-weight: 600; font-size: 0.82rem;
  color: #0b1233; background: var(--signal);
  border: 0; border-radius: 8px; padding: 0.42rem 1.05rem; cursor: pointer;
  white-space: nowrap;
  /* Wave 2 set a 44px minimum target for every control on this page. */
  min-height: 44px; display: none; align-items: center;
  transition: background-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}
.home .decision[data-enhanced] .decision__act { display: inline-flex; }
.home .decision__act:hover { background: #ffe54d; }
.home .decision__act:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.home .decision__act[aria-pressed="true"] {
  background: transparent; color: rgba(255,255,255,0.72);
  box-shadow: inset 0 0 0 1.5px rgba(255,255,255,0.28);
}

.home .decision__status {
  font-family: var(--font-mono); font-size: 0.62rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--signal); border: 1px solid rgba(255,218,0,0.36);
  border-radius: 999px; padding: 2px 10px; white-space: nowrap;
  transition: color var(--motion-base) var(--ease-standard),
              border-color var(--motion-base) var(--ease-standard),
              background-color var(--motion-base) var(--ease-standard);
}
.home .decision__status.is-approved {
  color: #6ee7a0; border-color: rgba(110,231,160,0.42);
  background: rgba(110,231,160,0.10);
}

/* The committed bar keeps the same yellow. Turning it green would say the
   approval was good news; it is neither. It is simply now counted. */
.home .job__bar span.is-committed { box-shadow: 0 0 0 1px rgba(255,255,255,0.22); }

@media (prefers-reduced-motion: reduce) {
  .home .decision__status, .home .decision__act { transition: none; }
}

/* ==========================================================================
   13. THE SYSTEM GRID, RESTORED AND RE-SITED
   ==========================================================================
   V5 gave the four parts of Crux their own dark band under "What Crux does",
   sitting between the problem and the workflow demo as an unrelated block.

   They belong to Line of Sight, ahead of the step-through: name the four
   places money passes through, then walk one invoice through all four. The
   grid stops being a feature list and becomes the legend for the demo.

   The cells keep their navy fill and so read as four dark keys laid on the
   paper stage, which is also what the blueprint language would do.
   ========================================================================== */

.home .sysintro__lead {
  max-width: 62ch; font-size: 1.05rem; line-height: 1.6;
  color: var(--ink-body); margin: 0 0 1.6rem;
}
.home .sysintro__then {
  margin: 1.6rem 0 var(--bay-tight);
  font-family: var(--font-mono); font-size: 0.78rem;
  letter-spacing: 0.04em; color: var(--ink-muted);
}
.home .sysintro__then::before {
  content: ""; display: inline-block; width: 1.6rem; height: 1px;
  background: var(--navy); vertical-align: middle; margin-right: 0.7rem;
  opacity: 0.5;
}

/* The stage lead's measure. `.home p` caps paragraphs at 60ch, which at this
   size renders 81 real characters per line: `ch` is the width of "0", and DM
   Sans's zero is narrower than its average glyph, so the unit over-reports by
   about a third. The cap is therefore set from the measured value, and scoped
   to beat `.home p` on specificity rather than relying on source order. */
.home .stagehead__lead { max-width: 46ch; }

/* ==========================================================================
   14. ONE VOICE ACROSS THE SITE
   ==========================================================================
   V6 shipped as two families that had never been put side by side. Home,
   Platform, the capability pages and Pricing are built on home.css, where
   headlines are DM Sans on warm paper. About, Solutions, Contact and the
   success page are built on marketing.css + elevation.css, where headlines
   are Bebas Neue in full caps on a cold blue-grey.

   Measured, the second family also had its scale inverted: h1 rendered at
   51px and h2 at 72px, so on Contact the page title "Book a Demo." was
   visibly smaller than the section heading beneath it. A visitor moving
   between the two halves of the site was not reading one product.

   Three corrections, all scoped to the marketing family so the home family
   is untouched:

   1. HEADLINES SPEAK IN DM SANS. Bebas is magnificent and it is structure:
      stage markers, eyebrows, the rail. Set as a headline in full caps it
      stops being a voice and becomes a sign, and long titles get hard to
      read. This is the same division the homepage already runs on.

   2. THE SCALE DESCENDS. h1 above h2 above h3, from one ramp.

   3. THE PAPER IS WARM. home.css's own note calls for "construction
      paperwork, not cold fintech grey", then elevation.css set the page to
      #eef2fa, which is precisely cold fintech grey. Remapped onto the warm
      family the rest of the site already uses. Only the neutrals move; navy,
      blue and yellow are untouched.
   ========================================================================== */

/* ---- 3. Warm paper, replacing the blue-grey ---------------------------- */
:root {
  --paper-0:   #ffffff;
  --paper-50:  #faf9f5;
  --paper-100: #f4f2ec;   /* was #eef2fa */
  --paper-200: #e9e5d9;   /* the yard tone, so the two families share a floor */
  --paper-line:      rgba(26, 38, 96, 0.11);
  --paper-line-soft: rgba(26, 38, 96, 0.05);
}

/* ---- 1 + 2. Headline voice and scale ---------------------------------- */
body:not(.home) main h1,
body:not(.home) main h2,
body:not(.home) main h3,
body:not(.home) main h4,
body:not(.home) .hero__title,
body:not(.home) .section-header__title,
body:not(.home) .cta-band__title,
body:not(.home) .contrast__title,
body:not(.home) .mcard__title,
body:not(.home) .rolecard__q,
body:not(.home) .step__title {
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: -0.02em;
  text-transform: none;
}

body:not(.home) main h1,
body:not(.home) .hero__title {
  font-size: clamp(2.4rem, 4.4vw, 3.6rem);
  line-height: 1.05;
  max-width: 18ch;
}
body:not(.home) main h2,
body:not(.home) .section-header__title,
body:not(.home) .cta-band__title {
  font-size: clamp(1.8rem, 3.2vw, 2.6rem);
  line-height: 1.1;
}
body:not(.home) main h3,
body:not(.home) .contrast__title { font-size: clamp(1.25rem, 1.9vw, 1.5rem); line-height: 1.2; }
body:not(.home) main h4,
body:not(.home) .mcard__title,
body:not(.home) .rolecard__q,
body:not(.home) .step__title { font-size: 1.15rem; line-height: 1.25; }

/* ---- Buttons say what happens, in the voice of the page ---------------- */
body:not(.home) .btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.005em;
  text-transform: none;
}

/* ==========================================================================
   15. THE HERO PROOF, MADE READABLE
   ==========================================================================
   Platform and the five capability pages all opened the same way: a headline
   at four lines beside two product screenshots, the second laid over the
   first at 56% width. Those screenshots are 787px and 1047px wide natively
   and were being drawn at roughly 550px and 358px, a 2.9x downscale on the
   inset. Dense financial tables do not survive that. They read as grey
   texture, and on Bill Tracker the absolutely positioned caption collided
   with the overlapping image.

   Worse, the page was arguing the opposite of what it showed: an enormous
   claim about financial control, illustrated by evidence too small to read.

   Both screenshots now stack at full column width, each in the same bezel
   the homepage panel uses, with the caption below where nothing can land on
   top of it. Nothing is lost by unstacking them: every one of these pages
   already shows both images again, larger, further down.
   ========================================================================== */

.home .hero-proof {
  max-width: 44rem; padding-bottom: 0;
  display: grid; gap: 0.9rem;
}
.home .hero-proof .shot {
  position: static; width: 100%;
  border: 1px solid rgba(26, 38, 96, 0.16);
  border-radius: 12px; overflow: hidden;
  background: var(--card);
  box-shadow: 0 18px 44px rgba(20, 26, 60, 0.14);
}
.home .hero-proof .shot img { display: block; width: 100%; height: auto; }
/* "Product interface shown with illustrative data." is the product-truth
   label on the hero screenshot. It was 11.52px here, below the floor set in
   section 21, because this rule is (0,3,0) and the floor is (0,2,0). It is
   the caption that stops the screenshot being read as a live product claim,
   so it reads at note size. */
.home .hero-proof .shot-cap {
  position: static; margin: 0.25rem 0 0;
  font-family: var(--font-mono); font-size: var(--ui-note);
  letter-spacing: 0.02em; color: var(--ink-muted);
}

/* With the media carrying real weight, the headline no longer has to shout
   to hold the fold. Four lines at this size was a wall, not a hierarchy. */
.home .hero__title {
  font-size: clamp(2.3rem, 3.9vw, 3.4rem);
  line-height: 1.06; letter-spacing: -0.022em;
  max-width: 17ch;
}
.home .hero__grid { align-items: start; }

/* ==========================================================================
   16. THE MOBILE FOLD
   ==========================================================================
   On a 390px screen the hero read as a wall of words: eyebrow, three-line
   headline, four-line lede, two stacked buttons and a six-line note, and
   only then the panel. The one thing that makes the argument, three jobs
   with one decision waiting, sat entirely below the fold.

   `display: contents` lets the copy block's children join the hero's own
   flow, so the panel can be lifted directly under the headline without
   duplicating markup or changing the desktop layout or the reading order
   for anything that reads the DOM. Claim, then evidence, then explanation.
   ========================================================================== */

@media (max-width: 61.99rem) {
  .home .tower__grid { display: flex; flex-direction: column; gap: 1.5rem; }
  .home .tower__copy { display: contents; }
  .home .tower__eyebrow { order: 1; }
  .home .tower__title   { order: 2; }
  .home .panel          { order: 3; }
  .home .tower__lede    { order: 4; }
  .home .tower__actions { order: 5; }
  .home .tower__note    { order: 6; }

  /* The headline carried desktop's measure into a column a third the width. */
  .home .tower__title { font-size: clamp(2rem, 8.6vw, 2.75rem); }
  .home .tower__actions { display: grid; gap: 0.7rem; }
  .home .tower__actions .btn { width: 100%; }
}

/* The footer's column labels are h2 elements. They are labels, not page
   headings, and the ramp above must not reach them: scoping the ramp to
   <main> keeps the footer set the way the shell intends it. */

/* ==========================================================================
   17. CONTEXTUAL LINKS TO THE SECONDARY DESTINATIONS
   ==========================================================================
   Proof and Outcomes, and Resources, are deliberately kept out of the primary
   navigation: the top-level nav carries the decision path, and adding two more
   items to it would dilute that. They are reachable from the footer on every
   page, and from a sentence placed wherever the reader's next question is the
   one that destination answers.

   Styled as prose with an underlined link rather than as another button.
   These are detours a reader chooses, not steps the funnel pushes.
   ========================================================================== */

.home .ctx-link {
  margin-top: 1.5rem;
  font-size: 1rem; line-height: 1.6; color: var(--ink-body);
  max-width: 62ch;
}
.home .ctx-link a {
  color: inherit; font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--signal);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}
.home .ctx-link a:hover { text-decoration-thickness: 3px; }
.home .sec--dark .ctx-link, .home .stage--tower-0 .ctx-link,
.home .stage--tower-1 .ctx-link, .home .stage--tower-2 .ctx-link {
  color: rgba(255, 255, 255, 0.82);
}

/* ==========================================================================
   18. LOGO PROMINENCE
   ==========================================================================
   The masthead gave the Crux mark 34px inside an 80px bar, which left it
   reading as a small label rather than as the thing that owns the page. It is
   the only brand asset above the fold on every route and it was the quietest
   element in the header.

   Raised to 44px in the masthead and 38px in the footer. The masthead bar
   grows to 88px to keep the optical padding balanced, which also gives the
   nav items more room. Below 60rem the mark steps back down, because the
   mobile bar has a menu button competing for the same line.
   ========================================================================== */

.masthead .brand__logo { height: 44px; }
.masthead__inner { min-height: 88px; }
.home .masthead__inner { min-height: 88px; }
.footer .brand__logo { height: 38px; }

@media (max-width: 60rem) {
  .masthead .brand__logo { height: 36px; }
  .masthead__inner, .home .masthead__inner { min-height: 72px; }
}

/* ==========================================================================
   19. QUICKBOOKS BRANDING PRESENTATION
   ==========================================================================
   No licensed Intuit logo asset exists in this repository, so the wordmark is
   set in type. Within that constraint the presentation is now consistent
   everywhere it appears, and it follows the conventions a trademark owner
   expects of a third party:

     - The mark is always "QuickBooks" with the registered symbol, never
       abbreviated, never possessive, never a verb.
     - It is set in Intuit's green on a plain white surface (3.41:1) and never
       recoloured to Crux navy, which would imply ownership.
     - It is never placed inside a Crux-branded container.
     - The Intuit trademark and non-affiliation notice appears in the footer of
       all 14 routes, and beside the mark wherever the boundary is the subject.

   When the licensed asset arrives, replace .qb-logo__text with an <img
   class="qb-logo__img">; the sizing below already reserves the same box, so
   nothing else needs to move.
   ========================================================================== */

.home .qb-logo { min-height: 2.4rem; align-items: center; }
.home .qb-logo__text {
  font-family: var(--font-body); font-weight: 700;
  font-size: 1.55rem; line-height: 1.1; letter-spacing: -0.015em;
  color: #2CA01C; white-space: nowrap;
}
.home .qb-logo__text .tm {
  font-size: 0.46em; vertical-align: super; font-weight: 500;
  color: var(--ink-muted); margin-left: 0.12em;
}
.home .qb-logo__img { height: 30px; width: auto; display: block; }

/* The boundary panels are the one place the mark carries structural meaning:
   this side is not Crux. Give that side a neutral surface and a quiet rule so
   the distinction is visible before the labels are read. */
.home .qbflow__side--qb, .home .qb__side--qb {
  border-color: rgba(44, 160, 28, 0.28);
  box-shadow: inset 3px 0 0 rgba(44, 160, 28, 0.5);
}
.home .qbnote { border-left: 3px solid rgba(44, 160, 28, 0.5); }

/* ==========================================================================
   20. THE BEFORE AND AFTER, MADE VISIBLE
   ==========================================================================
   The comparison was a toggle between two panels of six rows each. Switching
   replaced every line at once, so the reader had to hold the previous six in
   memory to see what had changed. That is not a comparison, it is two lists.

   The "With Crux" side now carries the value it replaced, directly above the
   new one and set back in weight and colour. The difference is legible in one
   place, per row, without switching. The widget contract is unchanged: still a
   two-button toggle group, still exactly one panel visible, still fully
   readable with both panels open when JavaScript is off.
   ========================================================================== */

.home .shift__was {
  display: block; margin-bottom: 0.3rem;
  font-family: var(--font-mono); font-size: 0.72rem; line-height: 1.5;
  color: var(--ink-muted);
}
.home .shift__was-k {
  display: inline-block; margin-right: 0.5rem;
  font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-muted); opacity: 0.75;
}
.home .shift__now { display: block; }
.home .shift__panel--crux .shift__row dd { padding-left: 0.85rem; border-left: 2px solid var(--yellow); }

/* ==========================================================================
   21. THE LEGIBILITY FLOOR
   ==========================================================================
   A measurement pass across six routes found 37 distinct text styles rendering
   below 12.5px, and two diagram labels at 9.9px and 10.2px. Some of that is
   correct: a tracked uppercase mono label of two or three words is a different
   object from a sentence, and it reads fine small. Prose does not.

   So the floor is drawn by JOB, not by uniform size:

     NOTES AND INSTRUCTIONS (0.85rem / 1.65) are sentences the reader has to
     actually read: how to drive the workflow, what the estimator does and does
     not claim, what a figure is illustrative of, the Intuit notice. These were
     the worst offenders, sitting at 11.5px in muted ink, and they carry the
     honesty of the page. Anything the reader must read to use or trust the
     product now clears 13.6px.

     MICRO-LABELS (0.72rem) stay small deliberately. They are the system's
     voice: statuses, roles, units, tags. Short, tracked, uppercase, and never
     load-bearing prose.

   The two diagram labels are pulled up to the micro-label floor. Nothing on a
   production page should render below 11px.
   ========================================================================== */

.home {
  --ui-note:  0.85rem;   /* 13.6px: prose the reader must read */
  --ui-label: 0.72rem;   /* 11.5px: tracked uppercase micro-labels */
}

/* Notes, hints, captions and disclaimers: sentences, so they get sentence
   sizing and sentence leading. */
.home .demo__hint,
.home .demo__note,
.home .demo__cap,
.home .demo__trail-item,
.home .roi__hint,
.home .roi__note,
.home .roi__formula,
.home .budgetlab__hint,
.home .ba-cap,
.home .shot-cap,
.home .qbflow__disclaimer,
.home .qbnote__disc,
.home .sits__note,
.home .capbreadth__note,
.home .capture__note,
.home .prooffig__note,
.home .getcrux__note,
.home .metrics__note,
.home .reslist__note,
.home .dstate__note,
.home .shift__was,
.home .sysintro__then,
.home .team__from {
  font-size: var(--ui-note);
  line-height: 1.65;
}

/* The instruction that tells a visitor the workflow is steppable is the single
   most functional sentence on the homepage. It was 11.5px muted mono, which
   reads as a footnote. It is not a footnote. */
.home .demo__hint {
  color: var(--ink-body);
  border-left: 2px solid var(--yellow);
  padding-left: 0.75rem;
  margin-bottom: 1.1rem;
  max-width: 60ch;
}

/* Diagram labels were the smallest text on the site at 9.9px. */
.home .demo__blabel,
.home .demo__batag { font-size: var(--ui-label); line-height: 1.5; }

/* Micro-labels: hold the line at 11.5px, never below. */
.home .job__meta,
.home .decision__meta,
.home .shift__tag,
.home .compare__tag,
.home .capitem__role,
.home .capgroup__label,
.home .wf__chip,
.home .rolepanel__role { font-size: var(--ui-label); }

/* "A working session, not a hard sell." is a promise about what happens after
   the click, sitting directly under the primary CTA. It is trust copy, not a
   status tag, so it belongs on the note floor. */
.home .close-tower__reassure { font-size: var(--ui-note); }

/* ==========================================================================
   22. THE CORE, AS ONE WORKFLOW
   ==========================================================================
   The heading says "five capabilities, one workflow" and the section then
   listed five rows that read as five independent products. Nothing on the page
   showed the order, and order is the whole claim.

   Each row now carries its position in the workflow and a plain statement of
   what happens at that point, in the same numbered language the homepage
   stages and the register already use. A hairline runs down the left of the
   set so the five read as one path rather than five entries.
   ========================================================================== */

.home .capsys { position: relative; }
@media (min-width: 52rem) {
  .home .capsys::before {
    content: ""; position: absolute; left: 0; top: 1.6rem; bottom: 1.6rem;
    width: 2px; background: linear-gradient(var(--yellow), rgba(255,218,0,0.15));
  }
  .home .capitem { padding-left: 1.75rem; }
}
.home .capitem__step { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.35rem; }
.home .capitem__n {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.08em; color: var(--navy);
}
.home .capitem__when {
  font-family: var(--font-mono); font-size: 0.68rem;
  letter-spacing: 0.04em; color: var(--ink-muted);
}

/* ==========================================================================
   23. THE WIDER PLATFORM: AFFORDANCE AND READABILITY
   ==========================================================================
   Two problems, both of them costing trust rather than beauty.

   FALSE AFFORDANCE. The seventeen module names were each prefixed with a
   yellow arrow. An arrow means "this goes somewhere". None of them do: these
   are an inventory of what the platform covers, and Payment Applications in
   particular has no page and no capability claim anywhere on the site by
   design. A reader who clicks and gets nothing learns the page is lying to
   them in small ways. The arrow becomes a square marker, which is the same
   token the role lists already use for a non-navigating item.

   READABILITY OF THE CLOSING CONTENT. The paragraph that closes the page is
   the most carefully worded on the route: it is where Crux says it does not
   position a capability as production ready before it is. It was set at 11.8px
   in muted mono across six lines, which is how a site hides a disclaimer. It
   is not a disclaimer, it is the product-truth commitment, so it now reads as
   prose and the commitment gets its own line and weight.
   ========================================================================== */

.home .capgroup__list li::before { content: none; }
.home .capgroup__list li { padding-left: 0; }

/* MODULE DISCLOSURE
   The seventeen names were an inventory with no way to find out what any of
   them did. A visitor evaluating the platform could read the list and learn
   nothing from it.
   Each name is now a native <details>. That is deliberate rather than a
   scripted popover: <summary> is focusable, operable with Enter and Space,
   announced with its expanded state, works on touch, and works with no
   JavaScript at all. Hover is not involved anywhere, so nothing here is
   unreachable by keyboard or on a phone.
   Collapsed by default so the section stays an inventory at rest and only
   grows where the reader asks a question. */
/* The summary keeps its default display and the marker is positioned, rather
   than laying the two out on a grid track. Both render identically and both
   keep Enter and Space working, which was checked on the rendered page; this
   is simply the smaller change to an element whose default behaviour is doing
   the accessibility work here. */
.home .capmod__name {
  position: relative;
  cursor: pointer; list-style: none;
  padding: 0.15rem 0 0.15rem 1.4rem;
  color: var(--ink); font-size: 0.95rem; line-height: 1.5;
  border-radius: 4px;
}
.home .capmod__name::-webkit-details-marker { display: none; }
/* The marker is the same square the role lists use for a non-navigating item.
   It is not an arrow: an arrow means "this goes somewhere", and none of these
   go anywhere. */
.home .capmod__name::before {
  content: ""; position: absolute; left: 0.35rem; top: 0.72em;
  width: 7px; height: 7px; border-radius: 1px;
  background: var(--yellow-deep);
  transition: transform 160ms ease, background-color 160ms ease;
}
.home .capmod[open] .capmod__name::before { transform: scale(1.35); background: var(--navy); }
@media (prefers-reduced-motion: reduce) {
  .home .capmod__name::before { transition: none; }
}
@media (hover: hover) {
  .home .capmod__name:hover { color: var(--navy); background: rgba(26, 38, 96, 0.04); }
}
.home .capmod__name:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* DISCOVERABILITY
   The disclosure worked by every input path and almost nobody would have
   guessed it was there. The square marker is the site's token for a
   non-navigating item, so at rest the list read as an inventory and nothing
   said the names could be opened.

   A plus sign, sized down and set in the rule colour, sits at the end of each
   row and becomes a minus when open. It is the one glyph that means "there is
   more of this here" without meaning "this goes somewhere", which is the
   distinction the square marker was protecting. It costs one character per
   row, so the section stays an inventory rather than becoming a control panel. */
.home .capmod__name { padding-right: 1.5rem; }
.home .capmod__name::after {
  content: "+";
  position: absolute; right: 0.35rem; top: 50%; transform: translateY(-50%);
  font-family: var(--font-mono); font-size: 0.95rem; line-height: 1;
  color: var(--rule-strong);
  transition: color 160ms ease;
}
.home .capmod[open] .capmod__name::after { content: "\2212"; color: var(--navy); }
@media (hover: hover) {
  .home .capmod__name:hover::after { color: var(--navy); }
}
@media (prefers-reduced-motion: reduce) {
  .home .capmod__name::after { transition: none; }
}

/* One line above the set, so the affordance is named once rather than
   implied seventeen times. */
.home .capbreadth__hint {
  margin: 0 0 1.1rem;
  font-family: var(--font-mono); font-size: 0.72rem;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-muted);
}
.home .capmod__d {
  margin: 0.25rem 0 0.7rem 1.75rem;
  font-size: 0.85rem; line-height: 1.6; color: var(--ink-body);
  max-width: 34em;
}

/* The four groups hold different numbers of modules; letting them stretch to a
   common height stops the row reading as four unrelated tiles. */
.home .capbreadth { align-items: stretch; }
.home .capgroup { display: flex; flex-direction: column; }

.home .capbreadth__note {
  font-family: var(--font-body); font-size: var(--ui-note); line-height: 1.7;
  color: var(--ink-body); max-width: 68ch;
  border-top: 1px solid var(--rule); padding-top: 1.2rem;
}
.home .capbreadth__truth {
  display: block; margin-top: 0.7rem; font-weight: 600; color: var(--ink);
}

/* ==========================================================================
   24. THE CARD RADIUS SCALE
   ==========================================================================
   A sweep of twelve routes found six different corner radii doing the same
   job: 6, 8, 10, 12, 14 and 20px, all on rectangles with a background and a
   border. Individually each looks fine. Together they are why the site reads
   as a set of pages built at different times rather than as one product, and
   it is the kind of thing a visitor registers without being able to name.

   Three values, by role, and nothing else:

     8px   controls and chips, things you click or read at a glance
     12px  every card, everywhere, on every route
     14px  the demo frame alone, the one instrument housing on the site
     999px pills, which are a shape rather than a radius

   Rounding cards to a single value is the single highest-leverage
   consistency change available here, because cards are the most repeated
   object in the system.
   ========================================================================== */

/* Controls sit at 8px, matching .btn. */
.home .roi__formula { border-radius: 8px; }

.home .compare,
.home .demo__tracker,
.home .system,
.home .shot,
.home .channel,
.home .demo__queue,
.home .demo__record,
.home .demo__bacard,
.home .demo__bnode,
.home .demo__levels,
.home .edition,
.home .qbflow__side,
.home .qb__side,
.home .varsig__item,
.home .wf__step,
.home .mcard,
.home .ba,
.home .shift__panel,
.home .dstate-panel,
.home .metric,
.home .result,
.home .rescard,
.home .ownlink,
.home .capgroup,
.home .capnav__item,
.home .capture,
.home .dash__item,
.home .divlabor__side,
.home .apflow__step,
.home .budgetlab__inputs,
.home .budgetlab__out,
.home .team__card,
.home .panel { border-radius: var(--radius-md); }

/* The one exception, and it is deliberate: the demo frame is not a card, it is
   the housing the cards sit inside, and a slightly softer corner is what makes
   it read that way. */
.home .demo__frame { border-radius: 14px; }

/* Scraps stay square. Paper does not have rounded corners. */

/* The marketing pages carry no .home class, so their cards need the rule
   unscoped. .mcard was the last 20px card on the site. */
.mcard, .rolecard, .step, .contrast__col, .plate { border-radius: var(--radius-md); }

/* The Bill Tracker handoff section moved from a dark band to paper as part of
   the module-template normalization. Its lead had its colour hard-coded inline
   to the dark-surface token, which is exactly the class of bug the surface ink
   contract exists to prevent. It now uses the semantic token and will follow
   whatever surface it is placed on. */
.home .split__lead { color: var(--ink-body); font-size: 1.1rem; line-height: 1.6; }

/* ==========================================================================
   25. THE "WHAT STAYS BEHIND" GRID
   ==========================================================================
   The yellow rule was set on the grid container, so in the two-column layout
   it drew down the left edge of the container only: the left column got a
   rule, the right column got the 1.35rem indent that exists to clear a rule
   it never had. Six items presented as one set, three of them looking
   deliberately marked and three looking accidentally shifted.

   The rule moves onto each item, so both columns read the same way.
   ========================================================================== */

.home .stays { border-left: 0; }
.home .stay { border-left: 2px solid var(--yellow); }
@media (min-width: 52rem) {
  .home .stays { column-gap: clamp(2rem, 5vw, 3.5rem); }
}

/* ==========================================================================
   26. THE ESTIMATOR ON PAPER
   ==========================================================================
   The page used to end on 1,851px of unbroken navy: the estimator at #0b1233
   followed immediately by the close at #0b1233. Read at any distance that is
   not a section but a fade, and it made the last third of the homepage the
   heaviest and least readable part of it.

   The estimator moves to paper. The close stays navy, so the page still lands
   on the tower, but as one deliberate band rather than a long descent. Navy
   drops from 49% of the page to 24%.

   Most of the instrument needs no work: .roi is written against the --on-dark
   token family, which the light stages already remap to ink. What does need
   work is the four places yellow is used as a foreground, because #FFDA00 on
   #f4f2ec is unreadable. On paper those become navy and blue, which is the
   same relationship the rest of the light sections already use.
   ========================================================================== */

.home .stage--paper .roi__field label b { color: var(--navy); }
.home .stage--paper .roi__field input[type="range"] { accent-color: var(--navy); }
.home .stage--paper .roi__field input[type="range"]:focus-visible { outline-color: var(--blue); }
.home .stage--paper .roi__v--accent { color: var(--navy); }

/* The formula is the one place the arithmetic is shown in full, so it keeps a
   tinted plate to separate it from the inputs, in blue rather than yellow. */
.home .stage--paper .roi__formula {
  color: var(--navy);
  background: rgba(52, 70, 157, 0.05);
  border-color: rgba(52, 70, 157, 0.20);
}
.home .stage--paper .roi__out {
  background: var(--card);
  border-color: var(--rule-strong);
  box-shadow: 0 12px 32px rgba(20, 26, 60, 0.06);
}
/* The output figures carry the weight here, so they take ink rather than the
   muted token the dark surface gave them. */
.home .stage--paper .roi__v { color: var(--ink); }
.home .stage--paper .roi__k { color: var(--ink-body); }
.home .stage--paper .roi__metric--soft .roi__v { color: var(--ink-body); }
.home .stage--paper .roi__metric--soft .roi__k { color: var(--ink-muted); }

/* ==========================================================================
   27. THE CONTROL TOWER SIMULATION
   ==========================================================================
   The hero panel could approve one bill and undo it. That showed the page
   could react; it did not show why the product exists.

   It now runs four decisions, and each one moves something visible: the
   committed budget on a job, the queue count, a project's health, who owns
   the next move, and what crossed the accounting boundary. The strip below
   the panel carries the prompt, the controls for steps two and three, and a
   running ledger of what changed.

   Design constraints this section keeps:
     - the panel's own language is unchanged. This is the same instrument with
       more of it working, not a new component sitting inside the hero
     - nothing animates that is not a state change
     - the strip is hidden until enhanced, so with no JavaScript the panel is
       exactly the three projects and one Submitted row it was before, and
       there are no controls that do nothing
   ========================================================================== */

.home .panel__queue {
  margin-left: auto; margin-right: 0.75rem;
  font-family: var(--font-mono); font-size: 0.72rem;
  letter-spacing: 0.04em; color: var(--signal);
  white-space: nowrap;
}
.home .panel__queue.is-clear { color: var(--settled); }

/* The queue counter is a third child in a nowrap bar that previously held two.
   Title 62px + queue 140px + tag 129px plus padding forced the panel to 407px
   inside a 353px column at 390, and .tower{overflow:hidden} hid the result by
   clipping it rather than by scrolling, so a page-level overflow check came
   back clean while the right edge of the instrument was cut off.

   The bar wraps below 30rem and the counter takes the full second line. The
   panel is then bounded by its column like everything else. */
@media (max-width: 30rem) {
  .home .panel__bar { flex-wrap: wrap; row-gap: 0.35rem; }
  .home .panel__queue { margin-left: 0; margin-right: 0; order: 3; flex: 1 0 100%; }
}
/* Belt and braces: the instrument can never be wider than the column it sits
   in, whatever is put in its header later. */
.home .tower .panel { max-width: 100%; }

/* The health chip rides with the project's meta line, so a change in project
   state is read where the project is, not in a separate status area. */
.home .job__health {
  display: inline-block; margin-left: 0.5rem;
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.03em; color: var(--signal);
  border: 1px solid rgba(255, 218, 0, 0.35); border-radius: 999px;
  padding: 0.1rem 0.5rem;
}
.home .job__health.is-found { color: var(--settled); border-color: rgba(0, 200, 83, 0.4); }

.home .job__why {
  grid-column: 1 / -1; margin-top: 0.6rem;
  font-size: 0.85rem; line-height: 1.6; color: rgba(255, 255, 255, 0.78);
  border-left: 2px solid var(--signal); padding-left: 0.75rem;
  max-width: 46em;
}

/* Return is the other real outcome of an approval decision, so it sits beside
   Approve rather than being hidden behind it. Ghost weight: it is a valid
   choice, not the expected one. */
.home .decision__act--ghost {
  background: transparent; color: rgba(255, 255, 255, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.28);
}
.home .decision__act--ghost:hover { border-color: var(--signal); color: var(--signal); }
.home .decision__act--ghost.is-on,
.home .decision__act--ghost:disabled { opacity: 0.55; cursor: default; }
.home .decision__status.is-returned { color: var(--waiting); border-color: rgba(255, 179, 0, 0.45); }

/* The accounting boundary, revealed only once something has crossed it. */
.home .boundary-row {
  display: grid; gap: 0.15rem 1rem; align-items: baseline;
  padding: 0.85rem 1.1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(44, 160, 28, 0.07);
}
@media (min-width: 40rem) { .home .boundary-row { grid-template-columns: auto 1fr auto; } }
.home .boundary-row__k {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: rgba(255, 255, 255, 0.6);
}
.home .boundary-row__v { font-size: 0.9rem; color: rgba(255, 255, 255, 0.9); }
.home .boundary-row__s {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.04em;
  color: #6ee787; white-space: nowrap;
}

/* [hidden] is display:none in the UA sheet, which any class rule setting
   display will beat. Both of these stay hidden until enhanced, so the
   attribute has to be re-asserted here or the no-JS page renders a strip of
   controls that cannot do anything. Caught by loading the page with scripts
   disabled, not by reading the markup. */
.home .sim[hidden], .home .boundary-row[hidden] { display: none !important; }
.home .sim {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding: 1.1rem 1.1rem 1.25rem;
  display: grid; gap: 0.6rem;
}
.home .sim__head { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; }
.home .sim__step {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em;
  color: var(--signal); white-space: nowrap;
}
.home .sim__title {
  font-family: var(--font-body); font-weight: 600; font-size: 1rem;
  line-height: 1.35; color: #fff;
}
.home .sim__ask {
  margin: 0; font-size: 0.85rem; line-height: 1.65;
  color: rgba(255, 255, 255, 0.78); max-width: 52em;
}
.home .sim__pointer { color: var(--signal); }

.home .sim__acts { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.home .sim__btn {
  font-family: var(--font-body); font-weight: 600; font-size: 0.85rem;
  border-radius: 8px; padding: 0.6rem 0.95rem; min-height: 44px;
  cursor: pointer; border: 1px solid transparent;
}
.home .sim__btn--primary { background: var(--signal); color: var(--navy); }
.home .sim__btn--primary:hover { background: var(--yellow-deep); }
.home .sim__btn--ghost {
  background: transparent; color: rgba(255, 255, 255, 0.82);
  border-color: rgba(255, 255, 255, 0.28);
}
.home .sim__btn--ghost:hover { border-color: #fff; color: #fff; }
.home .sim__btn:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }

/* The ledger is the point of the whole strip: a running record of what each
   decision moved. It is append-only, so the visitor can see the trail build. */
.home .sim__ledger { list-style: none; margin: 0.2rem 0 0; padding: 0; display: grid; gap: 0.35rem; }
.home .sim__note {
  font-family: var(--font-mono); font-size: 0.72rem; line-height: 1.55;
  color: rgba(255, 255, 255, 0.72);
  padding-left: 1rem; position: relative;
}
.home .sim__note::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 5px; height: 5px; border-radius: 1px; background: var(--settled);
}
@media (prefers-reduced-motion: no-preference) {
  .home .sim[data-enhanced] .sim__note { animation: simnote 220ms var(--ease-standard, ease) both; }
  @keyframes simnote { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
}

.home .sim__out {
  justify-self: start; margin-top: 0.35rem;
  font-family: var(--font-body); font-weight: 600; font-size: 0.9rem;
  color: var(--signal); text-decoration: underline;
  text-decoration-color: rgba(255, 218, 0, 0.5); text-underline-offset: 4px;
}
.home .sim__out:hover { text-decoration-color: var(--signal); }

/* ==========================================================================
   28. STATE TRANSITIONS ON THE NEW SIMULATION SURFACES
   ==========================================================================
   A scan of every anchor, button and summary in <main> across six routes found
   exactly one interactive element with no hover rule, so this section is short
   on purpose. What it adds is motion on the three things the simulation makes
   change, because a state that snaps is harder to read as a state that
   changed. Nothing here animates anything that is not a state change, and all
   of it is off under reduced motion.
   ========================================================================== */

/* The four wider-platform group headers were the one control on the site with
   no hover feedback. */
@media (hover: hover) {
  .home .capgroup__label:hover { color: var(--navy); }
}
.home .capgroup__label { transition: color 160ms var(--ease-standard); cursor: pointer; }

@media (prefers-reduced-motion: no-preference) {
  /* Project health: Over budget -> Cause identified -> Assigned to PM. The
     colour carries the meaning, so let the colour move. */
  .home .job__health {
    transition: color var(--motion-base) var(--ease-standard),
                border-color var(--motion-base) var(--ease-standard);
  }
  /* The cause and the accounting row are states arriving, not decoration. A
     short rise reads as "this appeared because of what you just did". */
  .home .job__why,
  .home .boundary-row { animation: simreveal 260ms var(--ease-standard) both; }
  @keyframes simreveal { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
}
@media (prefers-reduced-motion: reduce) {
  .home .job__health { transition: none; }
  .home .job__why, .home .boundary-row { animation: none; }
}

/* ==========================================================================
   29. THE GUIDED OPERATIONAL SEQUENCE
   ==========================================================================
   The simulation went from four decisions to five, and the reason is that two
   of the old steps were doing two jobs each. Opening an over-budget job and
   giving it an owner are different acts with different consequences, and so
   are handing work to accounting and the books agreeing with it. Splitting
   them is what lets each action move more than one visible thing.

   What this section adds is the surfaces those extra moves need:

     - the invitation band, so the panel asks to be operated
     - an owner field on the escalated job, empty until somebody owns it
     - the reason record that a Return leaves behind
     - a stage track, so position in the sequence is legible without reading
     - sync state as a state, not a single green word that is always there

   Design constraints, unchanged from section 27: the panel's own language is
   not redrawn, nothing animates that is not a state change, and every surface
   here ships hidden so the no-JS panel is exactly what it was.
   ========================================================================== */

/* [hidden] is display:none in the UA sheet, and any class rule that sets
   display beats it. Every new surface below sets display, so every one of
   them has to re-assert the attribute or the no-JS page renders an invitation
   to operate an instrument that has no controls. */
.home .invite[hidden],
.home .decision__reason[hidden],
.home .job__owner[hidden],
.home .boundary-row__note[hidden] { display: none !important; }

/* The invitation. It sits directly above the first control the visitor
   touches, and it carries the decision row's tint and rule so the two read as
   one band: the part of the instrument that asks for something. The rule moves
   up to the invitation when the invitation is present, so there is never a
   double hairline. */
.home .invite {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.75rem;
  padding: 0.85rem 1rem 0.15rem;
  border-top: 1px solid rgba(255, 218, 0, 0.28);
  background: rgba(255, 218, 0, 0.06);
}
.home .invite:not([hidden]) + .decision { border-top: 0; }
.home .invite__lead {
  font-family: var(--font-body); font-weight: 600; font-size: 0.95rem;
  line-height: 1.35; color: #fff;
}
.home .invite__hint {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.03em;
  color: rgba(255, 255, 255, 0.62);
}

/* What a Return leaves behind. Returning is a real outcome, so it has to
   produce a record the same way approving produces a committed budget. */
.home .decision__reason {
  margin: 0; padding: 0.75rem 1rem 0.85rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 0.85rem; line-height: 1.6; color: rgba(255, 255, 255, 0.78);
}

/* Ownership rides with the job, because "who is fixing this" is a property of
   the job and not of the strip that asked the question. It appears empty on
   escalation, which is the point: raising something is not the same as
   somebody carrying it. */
.home .job__owner {
  grid-column: 1 / -1; margin-top: 0.5rem;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem 0.6rem;
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em;
}
/* 0.62 is the panel's established muted key, and it is also the floor here:
   0.45 measured 3.7:1 against the gradient behind this row, under the 4.5
   needed at 10.9px. Measured on the rendered pixel, not on the token. */
.home .job__owner-k {
  text-transform: uppercase; letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.62);
}
.home .job__owner-v { color: var(--signal); }
.home .job__owner-v.is-owned { color: var(--settled); }

/* Returning the item disables Approve, and a disabled control that still reads
   as the page's brightest call to action is a control the visitor will keep
   trying. Return already dims itself; Approve now does the same. */
.home .decision__act:disabled {
  opacity: 0.5; cursor: default; background: transparent;
  color: rgba(255, 255, 255, 0.6); border: 1px solid rgba(255, 255, 255, 0.22);
}
.home .decision__act:disabled:hover { background: transparent; }

/* Escalated is amber: raised, not resolved. Assigned turns it settled, which
   is what .is-found already does. */
.home .job__health.is-raised {
  color: var(--waiting); border-color: rgba(255, 179, 0, 0.45);
}

/* The stage track. Six segments, one per stage, and the only thing on the
   strip that says where you are without words. aria-hidden, because the step
   counter beside it already says "Step 3 of 6" in text. */
.home .sim__track {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: 4px;
}
.home .sim__seg {
  flex: 1 1 0; height: 3px; border-radius: 2px;
  background: rgba(255, 255, 255, 0.12);
}
.home .sim__seg.is-done { background: var(--settled); }
.home .sim__seg.is-here { background: var(--signal); }
@media (prefers-reduced-motion: no-preference) {
  .home .sim__seg { transition: background var(--motion-base) var(--ease-standard); }
}

/* Sync state as a state. The boundary row used to appear already green and
   already synced, which skipped the step the page is trying to make: crossing
   to accounting and landing in the books are two events. The row now opens
   neutral, goes amber while it is ready, and only turns green when QuickBooks
   has it. On the returned path it stays neutral and says so. */
.home .boundary-row { background: rgba(255, 255, 255, 0.045); }
.home .boundary-row.is-synced { background: rgba(44, 160, 28, 0.07); }
.home .boundary-row__s { color: rgba(255, 255, 255, 0.72); }
.home .boundary-row__s.is-ready { color: var(--waiting); }
.home .boundary-row__s.is-synced { color: #6ee787; }
.home .boundary-row__s.is-held { color: rgba(255, 255, 255, 0.6); }
.home .boundary-row__note {
  grid-column: 1 / -1; display: block; margin-top: 0.35rem;
  font-family: var(--font-mono); font-size: 0.68rem; line-height: 1.55;
  /* 0.72 is the ledger note's colour, and the same reason applies: at 10.9px
     this needs 4.5:1, and it has to clear it against the lighter neutral fill
     the row uses when nothing has synced, not only the green one. */
  color: rgba(255, 255, 255, 0.72);
}

@media (prefers-reduced-motion: no-preference) {
  /* Three more states arriving because of something the visitor did. Same
     260ms rise the cause line and the boundary row already use. */
  .home .job__owner,
  .home .decision__reason,
  .home .boundary-row__note { animation: simreveal 260ms var(--ease-standard) both; }
  .home .job__owner-v,
  .home .boundary-row__s {
    transition: color var(--motion-base) var(--ease-standard);
  }
}
@media (prefers-reduced-motion: reduce) {
  .home .job__owner,
  .home .decision__reason,
  .home .boundary-row__note { animation: none; }
  .home .sim__seg, .home .job__owner-v, .home .boundary-row__s { transition: none; }
}

/* ==========================================================================
   30. THE QUICKBOOKS INTEGRATION LOCKUP AND THE BRANDED WORD
   ==========================================================================
   Two related jobs.

   The lockup puts the official Intuit asset in the first screen, directly
   under the headline, where the positioning claim is made. It is a supporting
   line and a mark, not a second brand: the label is mono at 0.75rem and the
   asset is 28px, against a 56px headline and the Crux mark in the masthead.

   Placement is a fold problem, not a taste one. Under 62rem the hero reorders
   (section 16) and the lede drops past 1190px on a 390 screen, so a lockup
   sitting with the lede would never be seen. It takes order 3, directly under
   the headline and above the panel, which puts it inside the first viewport
   at every reviewed width.

   The branded word gives plain-text "QuickBooks" the approved Intuit green in
   positioning copy, so the text and the asset read as one system. It stays
   selectable, translatable text: no image is ever substituted into a sentence.
   ========================================================================== */

.home .heroqb {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.35rem 0.7rem;
  /* The lower margin matters: a graphic sitting 6px off the first line of the
     lede reads as part of the paragraph rather than as its own statement. */
  margin: 1.2rem 0 1.15rem;
}
.home .heroqb__label {
  font-family: var(--font-mono); font-size: 0.75rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-muted, #626a8c);
}
/* The asset carries the name, so the label plus the alt text reads as one
   sentence to a screen reader: "Built for contractors running on QuickBooks". */
.home .heroqb__logo { height: 28px; width: auto; display: block; }

/* Above the fold on every width, so it is never deferred. */

@media (max-width: 61.99rem) {
  /* Slot the lockup between the headline and the panel, and push the rest of
     the reordered hero down one. Same specificity as section 16, later wins. */
  .home .heroqb        { order: 3; margin-top: 0.15rem; }
  .home .panel         { order: 4; }
  .home .tower__lede   { order: 5; }
  .home .tower__actions{ order: 6; }
  .home .tower__note   { order: 7; }
  .home .heroqb__logo  { height: 26px; }
}

/* The branded word. Semibold because the green alone is not a strong enough
   signal at body size.

   The colour is a token because text and asset need different values, and this
   was measured rather than guessed. Official Intuit green, #2CA01C, runs 2.89:1
   to 3.41:1 against the surfaces this text actually lands on, against the 4.5:1
   WCAG AA needs at these sizes. Semibold does not rescue it: 600 is not "bold"
   for the large-text exemption, and the lede is 17px everywhere but desktop.

   #1F7014 is the same hue at 70%. 75% was not quite enough: between roughly
   600px and 991px the Control Tower panel's drop shadow falls across the hero
   lede and darkens the surface from (244,242,236) to (224,223,220), where 75%
   read 4.19:1. 70% measures 4.65:1 in that band and 6.20:1 on the white
   capability cards, so it clears AA at every width with headroom.

   This governs TEXT ONLY. The official SVG is never recoloured and renders at
   #2CA01C wherever the mark itself appears. */
:root { --qb-green: #1F7014; }
.home .qbword { color: var(--qb-green); font-weight: 600; }

/* The workflow demo's boundary board names Crux and QuickBooks as a pair of
   plain-text labels. It gets the branded word's colour so the text system is
   consistent, and nothing else: no logo goes inside that compact diagram,
   where it would compete with the official mark used elsewhere on the page. */
.home .demo__bnode--qb .demo__bname { color: var(--qb-green); }
.home .qbword .tm {
  font-size: 0.58em; vertical-align: super; line-height: 0;
  font-weight: 400; color: var(--ink-muted, #626a8c);
}

/* "QuickBooks(R)-based" is a hyphenated compound, and a line break after that
   hyphen leaves the mark and its registered symbol stranded at the end of a
   line. Holding the compound together is safe at every width: the whole token
   is 132px at 390 inside a 350px column, and 118px at 320 inside 280px, so it
   never becomes the thing that forces an overflow. Applied to the compound
   only, never to a whole sentence. */
.home .qbnb { white-space: nowrap; }
