/* Restructure layer. Loaded after app.css, which still holds the tokens and
   the base components; this file adds only what the chapter / sub-feature
   composition needs on top. Named v2 because that is what this build was
   called while it was being compared against the old one — see
   docs/marketing/useorigin-reference-analysis.md. */

/* Chapter opener — the page's second-level voice. One claim, one line. */
.chapter {
  padding-top: calc(var(--section-gap) * 1.1);
  padding-bottom: 8px;
  position: relative;
}

/* Title left, lead bottom-right of the same rule — a narrow left column
   inside a 1200px container left the right half dead and forced short
   titles to wrap on a dangling word. */
.chapter-head {
  border-top: 1px solid var(--slate);
  padding-top: 28px;
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  column-gap: 64px;
}

.chapter-index {
  grid-column: 1;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ash);
}

.chapter-title {
  grid-column: 1;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(38px, 5.2vw, 68px);
  line-height: 0.98;
  letter-spacing: -0.01em;
  color: var(--paper);
  margin: 14px 0 0;
  text-wrap: balance;
}

.chapter-lead {
  grid-column: 2;
  grid-row: 2;
  align-self: end;
  padding-bottom: 10px;
  font-size: 17px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--fog);
  text-wrap: pretty;
}

/* Sections inside a chapter sit closer to it than to the page */
.section--in-chapter {
  padding-top: 56px;
  padding-bottom: 72px;
}

/* A chapter already carries the big claim, so a section inside one drops
   to sub-feature weight and left alignment — two stacked serif headlines,
   one centred and one not, read as a mistake. */
.section--in-chapter .section-header {
  margin: 0 0 48px;
  max-width: 640px;
  text-align: left;
}

.section--in-chapter .section-title {
  font-size: clamp(26px, 3vw, 34px);
  line-height: 1.06;
  margin-bottom: 14px;
}

.section--in-chapter .section-desc {
  font-size: 16px;
}

/* Sub-feature — a named unit under a chapter, quieter than a section title */
.subfeature-title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(26px, 3vw, 34px);
  line-height: 1.06;
  letter-spacing: -0.005em;
  color: var(--paper);
  margin-bottom: 14px;
  text-wrap: balance;
}

/* Proof strip — named people, not anonymous icon boxes */
.proof-strip {
  padding: 56px 0 64px;
  border-top: 1px solid var(--hairline-color);
  border-bottom: 1px solid var(--hairline-color);
  background: var(--carbon);
}

.proof-lead {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 32px;
  max-width: 620px;
}

.proof-lead p {
  font-size: 17px;
  font-weight: 300;
  color: var(--mist);
}

.proof-quotes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-bottom: 32px;
}

.proof-quote {
  border-left: 1px solid var(--slate);
  padding-left: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.proof-quote p {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 300;
  line-height: 1.3;
  color: var(--bone);
}

.proof-quote cite {
  font-family: var(--font-mono);
  font-size: 11px;
  font-style: normal;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ash);
}

/* Visible while the copy is unfilled — never ship a placeholder quote live */
.proof-quote.is-placeholder p {
  color: var(--ash);
  font-style: italic;
}

.proof-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ash);
  padding-top: 24px;
  border-top: 1px solid var(--hairline-color);
}

@media (max-width: 900px) {
  .proof-quotes { grid-template-columns: 1fr; }
  .chapter { padding-top: var(--section-gap); }
  .chapter-head { grid-template-columns: 1fr; }
  .chapter-lead {
    grid-column: 1;
    grid-row: auto;
    padding-bottom: 0;
    margin-top: 18px;
  }
}


/* Only one card in the problem grid carries media now, so cards stop
   stretching their split-box to the row height and just end where they end. */
#problem .bento-card { justify-content: flex-start; }
#problem .bento-split-box { margin-top: 20px; }

/* ==========================================================================
   Feature cards — ported from the reference's .track__grid / .track__card
   (measured: 3 × 448px, gap 16px, card 448×700, radius 16px, padding 24px,
   caption pinned to the bottom). We have no photography, so the card ground
   is a tinted panel per module colour instead of a photo, and the product
   shot floats inside the frame rather than filling it.
   Variants: .feature-grid--3 (default) and .feature-grid--2.
   ========================================================================== */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.feature-grid--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.feature-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 28px;
  min-height: 480px;
  padding: 24px;
  border: 1px solid var(--slate);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--carbon);
  isolation: isolate;
  box-shadow: 0 1px 2px rgba(16, 18, 22, 0.04), 0 10px 24px rgba(16, 18, 22, 0.05);
  transition: transform var(--dur-state) var(--ease),
              border-color var(--dur-state) var(--ease),
              box-shadow var(--dur-state) var(--ease);
}

.feature-card:hover {
  transform: translateY(-3px);
  border-color: color-mix(in oklab, var(--tint, var(--accent)) 40%, var(--slate));
  box-shadow: 0 2px 4px rgba(16, 18, 22, 0.05), 0 16px 36px rgba(16, 18, 22, 0.1);
}

/* Tinted ground — the reference's photographic backdrop, in our vocabulary.
   Set --tint per card; falls back to the brand accent. */
.feature-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(120% 80% at 50% -10%, var(--tint, var(--accent)), transparent 62%),
    linear-gradient(180deg, var(--wash), transparent 45%);
  opacity: 0.16;
  pointer-events: none;
}

.feature-card__eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fog);
}

/* Frame for the floating fragment. Holds a .widget (DOM, preferred) or a
   cropped product image; either way it floats inset, never edge to edge. */
.feature-card__media {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 20px;
  min-height: 0;
}

/* An image fragment still gets the frame chrome; a .widget brings its own. */
.feature-card__media:has(img) {
  aspect-ratio: 4 / 3;
  border: 1px solid rgba(255,255,255,0.1); /* frames a dark image — stays white-alpha */
  border-radius: var(--radius-md);
  overflow: hidden;
  background: #08090b;
}

.feature-card__media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  transition: transform 0.4s var(--ease);
}

.feature-card:hover .feature-card__media img {
  transform: scale(1.02);
}

.feature-card__text {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.feature-card__title {
  font-size: 16px;
  font-weight: 500;
  color: var(--paper);
}

.feature-card__desc {
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--fog);
}

@media (max-width: 900px) {
  .feature-grid,
  .feature-grid--2 { grid-template-columns: 1fr; }
  .feature-card { min-height: 420px; }
}

/* ==========================================================================
   Product widgets — the reference's card fragments (portfolio balance,
   budget bars, markets grid, upcoming transactions) rebuilt as DOM, not
   pictures. Same anatomy every time: mono label rule, one large figure or a
   list of measured rows, everything else quiet.

   DOM rather than generated art on purpose: these depict the product, so
   they must stay true to it and re-theme with the tokens. Generated
   approximations of our own UI are the one thing the marketing asset rule
   in docs/marketing forbids.
   ========================================================================== */
.widget {
  width: 100%;
  background: linear-gradient(180deg, var(--wash), var(--wash-faint));
  border: 1px solid var(--hairline-color);
  border-radius: var(--radius-md);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.widget__label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fog);
  padding-bottom: 12px;
  border-bottom: 1px solid var(--hairline-color);
}

.widget__figure {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.widget__value {
  font-size: 30px;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
}

.widget__delta {
  font-size: 13px;
  color: #7fae91;
  font-variant-numeric: tabular-nums;
}

.widget__caption {
  font-size: 11px;
  color: var(--ash);
}

/* Measured rows — the budget-bar pattern: label, track, percentage */
.widget-rows {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.widget-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 10px;
  font-size: 12px;
  color: var(--mist);
}

.widget-row__pct {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--fog);
  font-variant-numeric: tabular-nums;
}

.widget-row__track {
  grid-column: 1 / -1;
  height: 3px;
  border-radius: var(--radius-pill);
  background: var(--hairline-color);
  overflow: hidden;
}

.widget-row__fill {
  display: block;
  height: 100%;
  width: var(--pct, 0%);
  border-radius: inherit;
  background: var(--tint, var(--accent));
}

/* File list — mono names, quiet meta */
.widget-files {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.widget-file {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  border: 1px solid var(--hairline-color);
  border-radius: var(--radius-sm);
  /* Black-alpha ground was a dark-theme leftover — a gray slab on light. */
  background: var(--obsidian);
}

.widget-file__name {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--bone);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.widget-file__meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ash);
  white-space: nowrap;
}

.widget-file__name s {
  color: var(--ash);
  text-decoration-color: var(--smoke);
}

/* ==========================================================================
   The problem — was five equal bento cards, each restating "problem → fix",
   which read as a table drawn as cards and left one card mostly empty. The
   reference never lists five things at equal weight: it names one enemy and
   moves. Statement plus anchoring figure on the left, a quiet numbered
   ledger on the right.
   ========================================================================== */
.problem-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  gap: 72px;
  align-items: start;
}

.problem-statement .section-title {
  margin-bottom: 16px;
}

.problem-statement .section-desc {
  max-width: 40ch;
}

.problem-widget {
  margin-top: 36px;
  max-width: 320px;
}

.widget__label--plain {
  border-bottom: 0;
  padding-bottom: 0;
  padding-top: 6px;
}

.problem-widget .widget__figure {
  align-items: baseline;
  gap: 10px;
}

.problem-widget .widget__value {
  font-family: var(--font-mono);
  font-size: 34px;
}

.ledger {
  list-style: none;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--slate);
}

.ledger-row {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 8px;
  padding: 22px 0;
  border-bottom: 1px solid var(--slate);
  transition: background-color var(--dur-state) var(--ease);
}

.ledger-row:hover {
  background: var(--wash-faint);
}

.ledger-row__num {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--ash);
  padding-top: 5px;
}

.ledger-row__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: 24px;
  line-height: 1.1;
  color: var(--paper);
  margin-bottom: 8px;
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}

.ledger-row__tag {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ash);
}

.ledger-row__desc {
  font-size: 15px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--fog);
}

/* The fix is the answer to the line above it, so it hangs off it rather
   than sitting in its own boxed chip. */
.ledger-row__fix {
  margin-top: 8px;
  padding-left: 16px;
  border-left: 1px solid var(--smoke);
  font-size: 14px;
  font-weight: 300;
  line-height: 1.45;
  color: var(--mist);
}

@media (max-width: 900px) {
  .problem-layout { grid-template-columns: 1fr; gap: 40px; }
  .problem-widget { max-width: none; }
}


/* The portal frame holds a live mock, not a screenshot, so it needs the
   window chrome's own surface rather than an image's edge-to-edge fill. */
#portal .showcase-frame {
  background: var(--carbon);
}

#portal .portal-dropzone-mockup {
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 22px;
}

#portal .dropzone-box {
  margin-bottom: 16px;
}

/* ==========================================================================
   Engine stage — was a 5-file screen recording plus a terminal log. The
   recording baked in the old lime accent and the log spoke to engineers.
   Now a scripted DOM demo (v2/v2.js) built from the same widget primitives,
   so it re-themes with the tokens and weighs nothing.
   ========================================================================== */
.stage-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.stage-count {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--ash);
  font-variant-numeric: tabular-nums;
}

.stage-count span {
  color: var(--paper);
}

/* Five segments, not a continuous bar: the pipeline has five discrete passes
   and the old ➔ boxes duplicated the step list on the left. */
.stage-track {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  margin-bottom: 22px;
}

.stage-track i {
  height: 2px;
  border-radius: var(--radius-pill);
  background: var(--wash-strong);
  transition: background var(--dur-state) ease;
}

.stage-track i.is-done {
  background: var(--accent);
}

.stage-pass {
  margin-bottom: 18px;
}

.stage-pass__title {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--paper);
  margin: 0 0 6px;
}

.stage-pass__note {
  font-size: 13px;
  line-height: 1.55;
  color: var(--fog);
  margin: 0;
  min-height: 40px;
}

/* 10px rise, no blur — the measured reference value, per-row stagger. */
.stage-pass__title,
.stage-pass__note,
[data-engine-demo] .widget-file {
  animation: stageIn 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955) backwards;
  animation-delay: var(--row-delay, 0s);
}

@keyframes stageIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

[data-engine-demo] .widget-file__name s {
  margin-right: 6px;
}

@media (prefers-reduced-motion: reduce) {
  .stage-pass__title,
  .stage-pass__note,
  [data-engine-demo] .widget-file {
    animation: none;
  }
}

/* The stage tracks the reader down the five steps instead of sitting in a
   pool of empty space beside them. Sticky, not pinned — the reference has no
   scroll-scrubbed sections and neither does this. */
#engine .engine-container {
  align-items: start;
}

#engine .engine-container > div:last-child {
  position: sticky;
  top: 88px;
}

@media (max-width: 900px) {
  #engine .engine-container > div:last-child { position: static; }
}

/* Review gauges — were three mono numbers in green / amber / blue. Amber on
   "0 unreviewed" read as a warning about good news, and semantic colour has
   no business in marketing chrome (it belongs inside product widgets only).
   Same figures, display face, one voice. */
#review .gauge-count {
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--paper);
}

#review .gauge-count span {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--fog);
  margin-left: 4px;
}

#review .gauge-header {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash);
}

.gauge-note {
  font-size: 12px;
  color: var(--fog);
  margin: 6px 0 0;
}

/* One cropped panel, not a whole dashboard. The full case-notes capture put a
   sidebar, an inbox list and a detail rail on screen at 700px wide — every
   one of them illegible. The reference always shows a single readable
   fragment. Crop is CSS over the existing capture; still a real screen, no
   re-shoot needed. Replace with a panel-level capture when we re-run
   capture-media.mjs (backlog item a). */
.shot-crop {
  overflow: hidden;
  aspect-ratio: 16 / 10;
}

.shot-crop img {
  width: 100%;
  display: block;
  transform: scale(1.75);
  transform-origin: 68% 62%;
}

/* ==========================================================================
   The engine list — was five bordered, shadowed cards, a box treatment that
   appears nowhere else on this page, next to a card carrying its own five
   progress segments. Two numbering systems and two visual languages in one
   section, which is what made it read as imported from somewhere else.
   Now the same ruled ledger as #problem, and the ledger IS the progress.
   ========================================================================== */
#engine .engine-steps {
  border-top: 1px solid var(--slate);
  gap: 0;
}

#engine .engine-step-item {
  background: none;
  border: 0;
  border-bottom: 1px solid var(--slate);
  border-radius: 0;
  box-shadow: none;
  padding: 20px 0 20px 16px;
  gap: 14px;
  position: relative;
}

/* A hairline that grows in on the active pass — the only marker needed once
   the boxes are gone. */
#engine .engine-step-item::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: center;
  transition: transform var(--dur-state) var(--ease);
}

#engine .engine-step-item:hover,
#engine .engine-step-item.active {
  background: var(--wash-faint);
  border-color: var(--slate);
  box-shadow: none;
}

#engine .engine-step-item.active::before {
  transform: scaleY(1);
}

#engine .step-num {
  background: none;
  /* It was a centred badge; as a bare numeral it must sit on the title's
     baseline, not float in the middle of the row. */
  display: block;
  width: auto;
  height: auto;
  border-radius: 0;
  align-self: start;
  color: var(--ash);
  font-size: 11px;
  letter-spacing: 0.1em;
  padding-top: 4px;
  transition: color var(--dur-state) var(--ease);
}

#engine .engine-step-item.active .step-num {
  color: var(--accent);
}

/* Display face on the pass names, matching .ledger-row__title. */
#engine .step-title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: 22px;
  line-height: 1.1;
  color: var(--paper);
  margin-bottom: 6px;
}

#engine .step-desc {
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--fog);
}

/* With the segments gone the card leads with the pass name, so the header
   holds only the live marker and the position. */
[data-engine-demo] .stage-head {
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line, var(--hairline-color));
  margin-bottom: 20px;
}

/* ==========================================================================
   Hero canvas — replaced a synthetic "command centre" of four KPI cards and
   an intake stream that exists nowhere in the app. It asserted speed in
   numbers; this shows the six things the product does, as symbols you can
   read across the room, each opening into its own proof.
   Cards are DOM, not captures: they re-theme with the tokens, and a zoomed
   screenshot would only magnify the stale accent baked into the old ones.
   ========================================================================== */
.canvas-hint {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ash);
  text-align: center;
  margin: 56px 0 14px;
}

.hero-canvas {
  position: relative;
  height: 600px;
  perspective: 1500px;
  margin-inline: -40px;
  padding-inline: 40px;
}

.hero-card {
  position: absolute;
  width: var(--w, 288px);
  height: var(--h, 200px);
  padding: 22px;
  border: 1px solid var(--slate);
  border-radius: var(--radius-lg);
  /* Solid card on the light ground — the old white-alpha glass vanished
     against paper. Depth now comes from shadow, not translucency. */
  background: var(--carbon);
  box-shadow: 0 1px 2px rgba(16, 18, 22, 0.04), 0 12px 28px rgba(16, 18, 22, 0.06);
  cursor: pointer;
  text-align: left;
  color: inherit;
  font: inherit;
  overflow: hidden;
  transform: translate(-50%, -50%) rotate(var(--rot));
  transition: transform var(--dur-item) var(--ease), opacity var(--dur-state) ease,
              border-color var(--dur-state) ease, box-shadow var(--dur-state) ease,
              width 0.45s var(--ease), height 0.45s var(--ease);
}

.hero-card:hover:not(.is-open) {
  border-color: color-mix(in oklab, var(--tint) 45%, var(--slate));
  box-shadow: 0 2px 4px rgba(16, 18, 22, 0.05), 0 18px 44px rgba(16, 18, 22, 0.11);
  transform: translate(-50%, -50%) rotate(var(--rot)) translateY(-5px);
}

/* One tint per card, all from the existing token family. This is what stops
   six cards reading as one component stamped six times. */
.hero-card::before {
  content: '';
  position: absolute;
  top: -30%;
  left: -10%;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--tint) 0%, transparent 68%);
  opacity: 0.22;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

.hero-card:hover::before,
.hero-card.is-open::before { opacity: 0.38; }

.hero-card[data-depth="back"] {
  background: color-mix(in oklab, var(--carbon) 55%, var(--void));
  border-color: var(--slate);
  box-shadow: 0 1px 2px rgba(16, 18, 22, 0.03), 0 6px 16px rgba(16, 18, 22, 0.04);
}

.hero-card[data-depth="front"] {
  background: var(--carbon);
  border-color: var(--smoke);
  box-shadow: 0 2px 4px rgba(16, 18, 22, 0.05), 0 16px 36px rgba(16, 18, 22, 0.09);
}

/* :not(.is-open) is load-bearing — .hero-canvas.has-focus .hero-card outranks
   .hero-card.is-open on specificity, so without it the card you just opened
   is dimmed along with the rest. */
.hero-canvas.has-focus .hero-card:not(.is-open) { opacity: 0.2; }

.hero-card.is-open {
  opacity: 1;
  z-index: 40;
  width: 372px;
  height: 268px;
  border-color: color-mix(in oklab, var(--tint) 55%, var(--slate));
  box-shadow: 0 4px 8px rgba(16, 18, 22, 0.06), 0 24px 56px rgba(16, 18, 22, 0.14);
  /* Keep the TOP edge where the closed card sat and grow downward only —
     centre-anchored expansion pushed the top row under the fixed header. */
  transform: translate(-50%, calc(-50% + (268px - var(--h, 200px)) / 2)) rotate(0deg);
}

.hero-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* Two layers cross-fading in place. */
.hc-face,
.hc-detail {
  position: absolute;
  inset: 22px;
  transition: opacity var(--dur-state) ease, transform 0.45s var(--ease);
}

.hc-face { display: flex; flex-direction: column; justify-content: space-between; }

/* Spans, because a <button> may not contain block elements. */
.hc-face > span, .hc-title, .hc-note, .hc-story,
.hc-chrome, .hc-dropbox, .hc-bubble { display: block; }
.hc-head, .hc-chrome-bar, .hc-pipe, .hc-stages, .hc-file, .hc-check, .hc-swatches { display: flex; }

.hc-detail { opacity: 0; transform: translateY(10px); pointer-events: none; }
.hero-card.is-open .hc-face { opacity: 0; transform: translateY(-10px); }
.hero-card.is-open .hc-detail { opacity: 1; transform: none; }

.hc-icon { color: var(--tint); line-height: 0; }
.hc-icon svg { width: 54px; height: 54px; stroke-width: 1.4; }

.hc-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 29px;
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--paper);
  margin-bottom: 4px;
}

.hc-note { font-size: 13px; color: var(--fog); line-height: 1.45; max-width: 30ch; }

.hc-head {
  justify-content: space-between;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--hairline-color);
  margin-bottom: 11px;
}

.hc-story {
  position: absolute;
  bottom: 0;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--fog);
}

/* Portal — the client's view, so it wears browser chrome */
.hc-chrome { border: 1px solid var(--slate); border-radius: var(--radius-sm); overflow: hidden; background: var(--obsidian); }
.hc-chrome-bar { align-items: center; gap: 5px; padding: 5px 8px; border-bottom: 1px solid var(--slate); font-family: var(--font-mono); font-size: 8px; color: var(--ash); }
.hc-chrome-bar b { width: 5px; height: 5px; border-radius: 50%; background: var(--smoke); }
.hc-dropbox { margin: 10px; border: 1px dashed var(--slate); border-radius: var(--radius-sm); padding: 9px; text-align: center; font-size: 10px; color: var(--fog); }
.is-open .hc-dropbox {
  border-color: color-mix(in oklab, var(--tint) 50%, transparent);
  background: color-mix(in oklab, var(--tint) 8%, transparent);
  transition: 0.4s ease 0.25s;
}

/* Engine — fills stage by stage, the order it actually runs in */
.hc-pipe { align-items: center; gap: 5px; margin-bottom: 12px; }
.hc-pipe i { flex: 1; height: 3px; border-radius: var(--radius-pill); background: var(--wash-strong); position: relative; overflow: hidden; }
.is-open .hc-pipe i::after {
  content: ''; position: absolute; inset: 0; background: var(--tint);
  transform: translateX(-101%); animation: hcFlow 0.5s var(--ease) forwards;
}
.is-open .hc-pipe i:nth-child(1)::after { animation-delay: 0.15s; }
.is-open .hc-pipe i:nth-child(2)::after { animation-delay: 0.4s; }
.is-open .hc-pipe i:nth-child(3)::after { animation-delay: 0.65s; }
.is-open .hc-pipe i:nth-child(4)::after { animation-delay: 0.9s; }
.is-open .hc-pipe i:nth-child(5)::after { animation-delay: 1.15s; }
@keyframes hcFlow { to { transform: translateX(0); } }

.hc-stages { justify-content: space-between; font-family: var(--font-mono); font-size: 8px; color: var(--ash); margin-bottom: 12px; }

.hc-file {
  align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 6px 8px; border: 1px solid var(--slate); border-radius: var(--radius-sm);
  background: var(--obsidian); font-family: var(--font-mono); font-size: 9.5px;
  color: var(--mist); margin-bottom: 5px;
}
.hc-file span:last-child { color: var(--ash); font-size: 8.5px; white-space: nowrap; }
.hc-file s { color: var(--ash); text-decoration-color: var(--slate); margin-right: 5px; }

/* Thread — messages arrive in sequence, like a thread does */
.hc-bubble { border-radius: var(--radius-md); padding: 7px 9px; font-size: 10.5px; line-height: 1.4; margin-bottom: 6px; max-width: 86%; }
.hc-bubble.is-you { background: color-mix(in oklab, var(--tint) 18%, transparent); color: var(--paper); margin-left: auto; }
.hc-bubble.is-them { background: var(--obsidian); color: var(--mist); }
.is-open .hc-bubble { animation: hcRise 0.4s var(--ease) backwards; }
.is-open .hc-bubble:nth-of-type(1) { animation-delay: 0.2s; }
.is-open .hc-bubble:nth-of-type(2) { animation-delay: 0.5s; }
@keyframes hcRise { from { opacity: 0; transform: translateY(8px); } }

/* Review — checks resolve one at a time, like the review does */
.hc-check { justify-content: space-between; gap: 8px; font-size: 11px; padding: 5px 0; border-bottom: 1px solid var(--hairline-color); }
.hc-check:last-of-type { border-bottom: 0; }
.hc-check em { font-style: normal; font-family: var(--font-mono); font-size: 9px; color: var(--pulse-green); }
.is-open .hc-check { animation: hcRise 0.35s var(--ease) backwards; }
.is-open .hc-check:nth-of-type(1) { animation-delay: 0.15s; }
.is-open .hc-check:nth-of-type(2) { animation-delay: 0.35s; }
.is-open .hc-check:nth-of-type(3) { animation-delay: 0.55s; }
.is-open .hc-check:nth-of-type(4) { animation-delay: 0.75s; }

/* Brand — the portal repainting in a client's colours */
.hc-swatches { gap: 6px; margin-bottom: 10px; }
.hc-swatches i { width: 20px; height: 20px; border-radius: var(--radius-sm); border: 1px solid var(--slate); }
.is-open .hc-swatches i { animation: hcPop 0.35s var(--ease) backwards; }
.is-open .hc-swatches i:nth-child(2) { animation-delay: 0.1s; }
.is-open .hc-swatches i:nth-child(3) { animation-delay: 0.2s; }
.is-open .hc-swatches i:nth-child(4) { animation-delay: 0.3s; }
@keyframes hcPop { from { opacity: 0; transform: scale(0.6); } }

/* Dashboard — the line draws itself. The data is not changing, so the reveal
   is the only honest thing to animate. */
.hc-chart { width: 100%; height: 84px; display: block; }
.hc-chart .hc-line { fill: none; stroke: var(--tint); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.is-open .hc-chart .hc-line { stroke-dasharray: 400; stroke-dashoffset: 400; animation: hcDraw 1.1s var(--ease) 0.15s forwards; }
@keyframes hcDraw { to { stroke-dashoffset: 0; } }
.hc-chart .hc-area { fill: url(#hcFade); stroke: none; opacity: 0; }
.is-open .hc-chart .hc-area { animation: hcFadeIn 0.6s ease 0.7s forwards; }
.hc-chart circle { fill: var(--tint); opacity: 0; }
.is-open .hc-chart circle { animation: hcFadeIn 0.3s ease 1.1s forwards; }
@keyframes hcFadeIn { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .is-open .hc-pipe i::after { animation: none; transform: translateX(0); }
  .is-open .hc-bubble, .is-open .hc-check, .is-open .hc-swatches i,
  .is-open .hc-chart .hc-line, .is-open .hc-chart .hc-area, .is-open .hc-chart circle {
    animation: none; opacity: 1; transform: none; stroke-dashoffset: 0;
  }
}

/* Below the shell pivot there is no hover to reveal with, and 300px cards
   cannot overlap legibly — so both layers stack and nothing is hidden. */
@media (max-width: 900px) {
  .hero-canvas {
    height: auto; perspective: none; margin-inline: 0; padding-inline: 0;
    display: grid; gap: 12px;
  }
  .hero-card, .hero-card.is-open {
    position: static; width: 100% !important; height: auto !important;
    transform: none !important; opacity: 1 !important;
  }
  .hero-canvas.has-focus .hero-card:not(.is-open) { opacity: 1 !important; }
  .hc-face, .hc-detail {
    position: static; inset: auto; opacity: 1; transform: none; pointer-events: auto;
  }
  /* Mobile shows face + detail stacked (no click-to-reveal), so justify-
     content: space-between — meant for a fixed-height closed card — had
     nothing to distribute against auto height, and icon/title/note bunched
     together. Explicit gap + a smaller icon fit the denser, taller stack. */
  .hc-face { display: flex; flex-direction: column; gap: 10px; margin-bottom: 18px; }
  .hc-icon svg { width: 38px; height: 38px; }
  .hero-card { padding: 20px; }
  .hero-card.is-open .hc-face { opacity: 1; transform: none; }
  .hc-story { position: static; margin-top: 10px; }
  .canvas-hint { display: none; }
}

/* Secondary action. The hero used to pair the primary button with a bare text
   link, which read as an afterthought beside a white pill; the reference gives
   both actions real weight. Tinted rather than solid so the primary still wins.

   Every metric here matches .btn-primary in app.css deliberately — the two sit
   side by side, so any drift shows up as a pair of mismatched pills. It had
   inherited font-weight 300 from the page and rendered visibly thinner than
   every other button on the site. */
.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 11px 20px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--hairline-strong);
  background: rgba(132, 125, 255, 0.14);
  color: var(--mist);
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--dur-state) var(--ease),
              background-color var(--dur-state) var(--ease),
              color var(--dur-state) var(--ease);
}

.btn-secondary:hover {
  border-color: var(--accent);
  background: rgba(132, 125, 255, 0.2);
  color: var(--paper);
}


/* ==========================================================================
   /book/ — the CTA fallback and a shareable link in its own right. The brief
   on the left exists to cut no-shows: someone who knows to bring a real
   folder turns up prepared, and someone who wanted a slide deck self-selects
   out before taking the slot.
   ========================================================================== */
.booking-section { padding-top: calc(var(--section-gap) * 0.7); }

.booking-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: 56px;
  align-items: start;
}

.booking-brief .section-title { margin-bottom: 14px; }
.booking-brief .section-desc { max-width: 46ch; margin-bottom: 34px; }

.booking-steps {
  list-style: none;
  padding: 0;
  margin: 0 0 32px;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--slate);
}

.booking-steps li {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 10px;
  padding: 18px 0;
  border-bottom: 1px solid var(--slate);
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--fog);
}

.booking-steps__num {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--ash);
  padding-top: 4px;
}

.booking-steps strong {
  display: block;
  font-weight: 400;
  color: var(--paper);
  margin-bottom: 3px;
}

.booking-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash);
  margin-bottom: 26px;
}

.booking-alt { font-size: 14px; color: var(--fog); margin: 0; }
.booking-alt a { color: var(--mist); text-decoration: underline; text-underline-offset: 3px; }
.booking-alt a:hover { color: var(--accent); }

/* Cal paints its own surface, so this is a frame, not a card. min-height
   reserves the space the iframe will take and stops the footer jumping up the
   page while the embed loads. */
.booking-cal {
  border: 1px solid var(--hairline-color);
  border-radius: var(--radius-lg);
  background: var(--carbon);
  overflow: hidden;
  min-height: 620px;
}

.cal-inline { width: 100%; height: 100%; min-height: 620px; overflow: auto; }

.booking-noscript { padding: 28px; color: var(--fog); font-size: 14px; }
.booking-noscript a { color: var(--accent); }

@media (max-width: 900px) {
  .booking-layout { grid-template-columns: 1fr; gap: 40px; }
  .booking-cal, .cal-inline { min-height: 540px; }
}

/* Sign-in was reachable only from the footer, so a returning customer landing
   on the marketing site had no visible way into the app. It sits beside the
   CTA rather than becoming a second button — two buttons of equal weight in a
   header make neither the primary action. Stays in .nav-actions, not
   .nav-links, because those are hidden below 992px and logging in must not
   be. */
.nav-login {
  font-size: 14px;
  color: var(--fog);
  text-decoration: none;
  padding: 8px 4px;
  margin-right: 16px;
  white-space: nowrap;
  transition: color var(--dur-state) var(--ease);
}

.nav-login:hover { color: var(--paper); }

/* Below 640 the bar cannot hold a wordmark, a sign-in link and a CTA — the
   button ran 8px past the viewport. Sign-in wins the space: the booking CTA
   is a few hundred pixels below in the hero, but a returning customer has
   nowhere else to go from here. */
@media (max-width: 640px) {
  .nav-login { font-size: 13px; margin-right: 0; }
  .site-header .btn-primary { display: none; }
}
