/* ============================================================================
   Purpose: Page-level composition for the framework. Hero first - everything
   else is added as its section lands. Tokens only.
   ========================================================================= */

/* --- Hero -------------------------------------------------------------------
   The car occupies the full frame; the copy sits over it on the left, held
   legible by a scrim rather than by a box. That is the difference between a
   configurator and a slide.
   ------------------------------------------------------------------------ */

/* Sections sit above the shared canvas. The whole content layer is transparent
   to the pointer and only the pieces that need input take it back - otherwise
   these full-width blocks lie across the car and eat every drag, which is
   exactly what stopped the car turning. */
.czf-main {
  position: relative;
  z-index: var(--z-raised);
  pointer-events: none;
}

/* Anything with a control in it has to be on this list. `.czf-main` is
   pointer-events: none so the car can be dragged through the content layer,
   which means a new section's buttons are dead until they are named here -
   that is exactly what happened to the 404's. */
.czf-hero__copy,
.czf-rig__panel,
.czf-result,
.czf-404__panel,
.czf-header,
.czf-footer { pointer-events: auto; }

/* The left column takes input on its heading and instruments, but the open
   space below them must stay transparent - that is where the car is, and the
   drag has to reach the canvas underneath. */
.czf-rig__head,
.czf-rig__instruments { pointer-events: auto; }
.czf-rig__side,
.czf-rig__view { pointer-events: none; }

/* --- Studio light -----------------------------------------------------------
   ONE light rig for the whole page, not one per section. Per-section gradients
   met at the section boundary and drew a visible seam across the page - the
   hero and the diagnostic have to read as one continuous room.
   ------------------------------------------------------------------------ */

.czf-room {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(52% 40% at 76% 14%, rgba(255, 196, 137, 0.055) 0%, transparent 70%),
    radial-gradient(46% 36% at 16% 78%, rgba(245, 168, 0, 0.06)   0%, transparent 72%),
    radial-gradient(70% 50% at 50% 50%, rgba(255, 138, 40, 0.022) 0%, transparent 78%);
}

.czf-rig::after {
  background:
    radial-gradient(50% 40% at 22% 62%, rgba(245, 168, 0, 0.05)  0%, transparent 70%),
    radial-gradient(46% 38% at 84% 24%, rgba(120, 196, 214, 0.05) 0%, transparent 72%);
}

.czf-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 100svh;
  padding-block: var(--space-96) var(--space-64);
  isolation: isolate;
  overflow: hidden;
}

/* No scrim. It was drawing a visible edge where the hero met the diagnostic
   and dulling the car behind it. The copy sits on the left where the room
   light is already lowest, so it holds contrast without one. */

/* The copy layer sits above the stage, but its wrappers are full-width blocks
   - which means they lie across the car and swallow the drag. So the layer is
   transparent to the pointer and only the copy column itself takes input. The
   right-hand side, where the car lives, passes straight through to the canvas. */
.czf-hero__inner {
  position: relative;
  z-index: var(--z-raised);
  width: 100%;
  pointer-events: none;
}

.czf-hero__copy { pointer-events: auto; }

.czf-hero__copy { grid-column: span 4; }

@media (min-width: 768px)  { .czf-hero__copy { grid-column: span 6; } }
@media (min-width: 1024px) { .czf-hero__copy { grid-column: span 6; } }

.czf-hero__title {
  margin-top: var(--space-20);   /* room under the eyebrow */
  font-size: var(--fs-hero);
  max-width: 17ch;
  /* The line-mask reveal needs the words clipped, so the h1 hides until
     animations.js has wrapped them. No JS → the fallback in initHero()
     restores it immediately. */
  opacity: 0;
}

.czf-js .czf-hero__title { opacity: 0; }
html:not(.czf-js) .czf-hero__title { opacity: 1; }

.czf-word    { display: inline-block; overflow: hidden; vertical-align: bottom; }
.czf-word__in { display: inline-block; will-change: transform; }

.czf-hero__kick {
  margin-top: var(--space-20);
  font-size: var(--fs-lead);
  line-height: var(--lh-heading);
  color: var(--c-shield);
  max-width: 30ch;
}

/* --- Action ----------------------------------------------------------------
   One button. The supporting line sits UNDER it, not above - above, it becomes
   another thing to read before acting.
   ------------------------------------------------------------------------ */

.czf-hero__act {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-12);
  margin-top: var(--space-32);
}

.czf-hero__note {
  margin: 0;
  max-width: 40ch;
  font-size: var(--fs-caption);
  color: var(--c-ink-3);
}

/* --- Trust strip ------------------------------------------------------------ */

.czf-trust {
  display: flex;
  flex-wrap: wrap;
  margin-top: var(--space-32);
  border-top: 1px solid var(--c-line-2);
}

.czf-trust__item {
  flex: 0 1 auto;
  padding-block: var(--space-16);
  padding-right: var(--space-32);
}

.czf-trust__n {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--weight-black);
  font-size: var(--fs-h6);
  line-height: var(--lh-tight);
  color: var(--c-ink);
  letter-spacing: var(--tracking-tight);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.czf-trust__n--clear { color: var(--c-clear); }

.czf-trust__l {
  display: block;
  margin-top: var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--c-ink-3);
  white-space: nowrap;
}

/* --- Scroll cue -------------------------------------------------------------- */

.czf-cue {
  position: absolute;
  left: 50%;
  bottom: var(--space-24);
  z-index: var(--z-raised);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-8);
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--c-ink-3);
  pointer-events: none;
}

.czf-cue__rail {
  width: 1px;
  height: var(--space-40);
  background: linear-gradient(180deg, var(--c-line-3), transparent);
  overflow: hidden;
}

.czf-cue__rail::after {
  content: "";
  display: block;
  width: 1px;
  height: var(--space-16);
  background: var(--c-shield);
  animation: czf-cue 2.4s var(--ease-in-out) infinite;
}

@keyframes czf-cue {
  0%        { transform: translateY(calc(var(--space-40) * -1)); opacity: 0; }
  30%, 70%  { opacity: 1; }
  100%      { transform: translateY(var(--space-40)); opacity: 0; }
}

@media (max-width: 767px) { .czf-cue { display: none; } }

/* --- Mobile ------------------------------------------------------------------
   Below 768 the car cannot share the frame with the copy and stay legible, so
   it sits behind, dimmed, and the scrim goes near-solid at the bottom.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .czf-hero { min-height: 92svh; padding-block: var(--space-80) var(--space-40); }
  .czf-hero__title { max-width: 13ch; }
}

/* ============================================================================
   RESPONSIVE - the rules that keep the layout honest below 1024.

   Two things caused the overflow and the missing header:
     1. The fixed canvas is 100vw wide. On a phone, 100vw INCLUDES the
        scrollbar gutter on some engines, which pushes the page 15-17px wide
        and produces a horizontal scrollbar the whole document inherits.
     2. The header is position:absolute inside a body that scrolls, and the
        hero starts at 100svh - so on short screens the header sat above the
        fold with nothing pinning it into view.
   ========================================================================= */

html, body { max-width: 100%; overflow-x: clip; }

.czf-stage--fixed { width: 100%; }

/* The car's parking bay in the hero. It only exists where the car is parked in
   the flow - above 1024 the car has the whole frame and this would be a hole
   in the hero. Declared before the breakpoint so the override below wins. */
.czf-hero__car { display: none; }

/* --- Body type ---------------------------------------------------------------
   Tabs under the car, hero only. They sit ON the stage layer rather than in the
   copy column, so they read as controls for the car and not as another thing to
   read before acting. Desktop pins them under the car on the right; below 1024
   they follow the car's bay in the flow.
   -------------------------------------------------------------------------- */

.czf-makes {
  position: absolute;
  z-index: var(--z-nudge);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
  /* Aligned to the CAR, not to the page.
     --czf-car-x is written by makes.js from the stage's own projection offset,
     because the car is not in the DOM and its position changes with the
     breakpoint. The 68.5% fallback is the hero framing, for the moment before
     the stage has loaded and for a browser with the 3D turned off. */
  left: var(--czf-car-x, 68.5%);
  transform: translateX(-50%);
  bottom: 26%;
  pointer-events: auto;
}

.czf-makes__tab {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: var(--space-8) var(--space-16);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--c-ink-3);
  background: var(--c-glass);
  border: 1px solid var(--c-line-2);
  backdrop-filter: blur(8px);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}

/* The same sweep the question options use. These tabs and those options are
   the only two things on the page you choose between, so they should answer
   the pointer the same way. */
.czf-makes__tab::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--grad-opt-sweep);
  opacity: 0;
  transform: translateX(calc(var(--space-8) * -1));
  transition: opacity   var(--dur-fast) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
  pointer-events: none;
}

.czf-makes__tab:hover { color: var(--c-ink); border-color: var(--c-line-3); }
.czf-makes__tab:hover::before { opacity: 1; transform: none; }

.czf-makes__tab[aria-selected="true"] {
  color: var(--c-ink-inv);
  background: var(--c-shield);
  border-color: var(--c-shield);
  font-weight: var(--weight-bold);
}

/* No sweep on the chosen tab - it is already solid gold, and a gold wash over
   gold is just a smudge. */
.czf-makes__tab[aria-selected="true"]:hover::before { opacity: 0; }

/* A notch on the selected tab, pointing up at the car it belongs to. The strip
   is positioned from the car's own centreline (--czf-car-x), so this is the
   one mark that ties the control to the thing it controls. */
.czf-makes__tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  width: var(--space-8);
  height: var(--space-4);
  background: var(--c-shield);
  transform: translate(-50%, -100%);
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
  pointer-events: none;
}

/* A swap is a model download. Say so, rather than letting the car sit frozen
   for a second while nothing appears to happen. */
.czf-makes.is-swapping .czf-makes__tab { opacity: 0.55; pointer-events: none; }
.czf-makes.is-swapping .czf-makes__tab[aria-selected="true"] { opacity: 1; }

/* A sliver running the length of the changeover on the tab you just chose.
   Dimming the row says "not now"; this says "working". It repeats because a
   model can take several seconds on a slow connection and the swap animation
   itself is only about a second. */
.czf-makes.is-swapping .czf-makes__tab[aria-selected="true"]::before {
  z-index: auto;
  inset: auto 0 0 0;
  height: 2px;
  opacity: 1;
  background: var(--c-ink-inv);
  transform: none;
  transform-origin: 0 50%;
  animation: czf-swap-sliver 1.06s var(--ease-out) infinite;
}

@keyframes czf-swap-sliver {
  0%   { transform: scaleX(0); opacity: 0.15; }
  60%  { transform: scaleX(1); opacity: 0.55; }
  100% { transform: scaleX(1); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .czf-makes__tab::before { display: none; }
  /* The progress cue is information, not decoration, so it stays - it just
     stops moving. */
  .czf-makes.is-swapping .czf-makes__tab[aria-selected="true"]::before {
    display: block;
    animation: none;
    opacity: 0.45;
  }
}

@media (max-width: 1023px) {
  .czf-makes {
    position: static;
    transform: none;
    justify-content: center;
    margin-bottom: var(--space-24);
  }
}

@media (max-width: 479px) {
  .czf-makes { gap: var(--space-4); }
  .czf-makes__tab { padding: var(--space-8) var(--space-12); letter-spacing: var(--tracking-wide); }
}

@media (max-width: 1023px) {

  /* The car does not share the frame with the copy at this width - it gets its
     own band, and the band moves. The mask that keeps it there is in
     stage.css; here we only stop the desktop column clip from applying. */
  .czf-stage--fixed { position: fixed; inset: 0; }

  /* Car first, then the hook. The hero is a column at this width so the
     reserved bay sits directly under the header, and the top padding comes
     off - the bay is the breathing room now. */
  .czf-hero {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    padding-block: var(--space-24) var(--space-48);
  }

  /* Both bays are sized to the car and little else. The car reads about 23svh
     tall at this width, so 28 leaves it breathing room without the hole of
     dead space a taller bay opens up above the copy. */
  .czf-hero__car {
    display: block;
    min-height: 28svh;
    margin-bottom: var(--space-8);
    /* The car is drawn behind this box, not in it. Nothing here may take the
       pointer or the drag never reaches the canvas. */
    pointer-events: none;
  }

  .czf-rig__grid { grid-template-columns: 1fr; gap: var(--space-16); }
  .czf-rig__side { position: static; gap: var(--space-16); }

  /* The second parking bay: the gap the car slides back into, after the
     gauges and before the question panel. Reserves real height for the same
     reason the hero bay does, and no more - the gauges and the question
     should stay within a thumb's reach of each other. */
  .czf-rig__view {
    display: block;
    min-height: 30svh;
    margin-block: calc(var(--space-8) * -1);
    pointer-events: none;
  }

  .czf-rig__panel { position: static; min-height: 0; }

  .czf-rig__instruments { max-width: none; }

  .czf-gate__grid { grid-template-columns: 1fr; }
}

@media (max-width: 767px) {

  .czf-hero { min-height: auto; }

  .czf-hero__act { width: 100%; }
  .czf-hero__act .czf-btn { width: 100%; }

  /* The hero's eyebrow on one line.
     "Free / 90 seconds / Result sent to you" is a single promise and wrapping
     it broke the three clauses across two lines with the last one orphaned.
     It needs 347px at 12px and has 303px, so the type comes down a step and
     the tracking with it - as with the stats below, the wide uppercase
     tracking was carrying more of the width than the letters were.

     Scoped to the hero. The other eyebrows on the page ("Your studio", "The
     diagnostic") are short, already fit, and are not part of this problem. */
  .czf-hero .czf-eyebrow {
    font-size: var(--fs-10);
    letter-spacing: var(--tracking-wide);
  }

  /* All three stats on ONE row. They are a single claim about the network read
     left to right, and two-up wrapped the third onto its own line where it
     read as an afterthought.

     No copy change: "2.5 million+" fits at 16px in the 106px each stat gets.
     The blocker was the LABEL - "Cars protected" needs 111px at 10px, and most
     of that is the wide uppercase tracking rather than the glyphs. Tightening
     the tracking buys back more than shrinking the type would, and costs less
     legibility. Values stay whatever the client typed into ACF. */
  /* Content-sized items with the slack shared between them, NOT three equal
     columns. Equal columns make the gaps unequal: each stat is left-aligned in
     its own track, so a short one like "150+" leaves a wide hole after it
     while "2.5 million+" nearly fills its track. Sizing to content and letting
     space-between distribute what is left is what actually puts the same gap
     between all three. */
  .czf-trust {
    gap: var(--space-8);
    flex-wrap: nowrap;
    justify-content: space-between;
  }

  .czf-trust__item {
    flex: 0 1 auto;
    min-width: 0;
    padding-right: 0;
  }

  .czf-trust__n { font-size: var(--fs-body); }

  .czf-trust__l {
    font-size: var(--fs-10);
    letter-spacing: var(--tracking-wide);
  }

  /* The two instruments stay SIDE BY SIDE, and each one restacks internally.
   *
   * They used to drop to one column here, which is the obvious move and the
   * wrong one: side by side is how you compare two numbers - it is the entire
   * reason there are two dials - and stacked they read as a list of unrelated
   * readings. What actually did not fit at this width was the gauge's own
   * left-to-right layout, so that is what changes: dial and score on one line,
   * the name, band and explanation underneath. See gauge.css. */
  .czf-rig__instruments { grid-template-columns: 1fr 1fr; gap: var(--space-16); }

  .czf-verdict__scores { grid-template-columns: 1fr; }
  .czf-verdict__acts .czf-btn { width: 100%; }
  .czf-studio { padding: var(--space-20); }
  .czf-step { padding-left: var(--space-48); }
  .czf-step::before { left: var(--space-16); }
}

@media (max-width: 479px) {
  .czf-rig__panel { padding: var(--space-16); }
  .czf-opt { padding: var(--space-12); gap: var(--space-12); font-size: var(--fs-caption); }
  .czf-rig__q { font-size: var(--fs-h5); }
  /* The dial's own size is set on the SVG in gauge.css now, because below 768
     the dial box is a two-column row (dial + score) that has to fill its
     column so the pair can centre in it. Shrinking the BOX here instead
     collapsed it back to the dial's width and left the pair hanging off the
     left edge while the caption under it stayed centred. */
}

/* ============================================================================
   404

   Same instrument vocabulary as the question panel: ruled surface, warm spill
   from one corner, corner crop marks. A dead URL is still the product talking,
   and a plain centred "page not found" would be the one screen in the whole
   build that looks like a default.
   ========================================================================= */

.czf-404 { display: grid; place-items: center; min-height: 68svh; }

/* `place-items: center` on the section centres its child - and that child is
   the full-width container, not the panel. The panel has to centre itself
   inside it, and its content has to be centred in turn: a left-ragged block
   floating in the middle of a centred card reads as a mistake. */
.czf-404__panel {
  position: relative;
  max-width: 52ch;
  margin-inline: auto;
  text-align: center;
  padding: var(--space-48);
  background: var(--grad-rig-grid), var(--grad-rig-spill), var(--grad-rig);
  border: 1px solid var(--c-line);
  box-shadow: var(--shadow-inset-top), var(--shadow-md);
}

/* The lit top edge and the crop marks, exactly as the question panel wears
   them. See quiz.css for why the marks are background layers on one element. */
.czf-404__panel::before {
  content: "";
  position: absolute;
  inset: -1px 0 auto 0;
  height: 1px;
  background: var(--grad-rig-edge);
  pointer-events: none;
}

.czf-404__panel::after {
  content: "";
  position: absolute;
  inset: var(--space-12);
  pointer-events: none;
  background-image:
    linear-gradient(var(--c-mark), var(--c-mark)), linear-gradient(var(--c-mark), var(--c-mark)),
    linear-gradient(var(--c-mark), var(--c-mark)), linear-gradient(var(--c-mark), var(--c-mark)),
    linear-gradient(var(--c-mark), var(--c-mark)), linear-gradient(var(--c-mark), var(--c-mark)),
    linear-gradient(var(--c-mark), var(--c-mark)), linear-gradient(var(--c-mark), var(--c-mark));
  background-size:
    var(--rig-mark-arm) 1px, 1px var(--rig-mark-arm),
    var(--rig-mark-arm) 1px, 1px var(--rig-mark-arm),
    var(--rig-mark-arm) 1px, 1px var(--rig-mark-arm),
    var(--rig-mark-arm) 1px, 1px var(--rig-mark-arm);
  background-position:
    0 0, 0 0, 100% 0, 100% 0,
    0 100%, 0 100%, 100% 100%, 100% 100%;
  background-repeat: no-repeat;
}

/* The code as a readout, not a headline. Tabular so the three digits sit on
   an even rhythm, and dim - it is a reference, not the message. */
.czf-404__code {
  margin: var(--space-24) 0 var(--space-8);
  font-family: var(--font-mono);
  font-size: var(--fs-h2);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-wide);
  line-height: var(--lh-tight);
  color: var(--c-ink-3);
}

.czf-404__title {
  font-size: var(--fs-h4);
  max-width: 20ch;
  /* The measure caps still apply, so they have to be centred themselves or
     the text block sits left inside a centred card. */
  margin-inline: auto;
  margin-bottom: var(--space-16);
}

.czf-404__line {
  color: var(--c-ink-2);
  max-width: 46ch;
  margin-inline: auto;
  margin-bottom: var(--space-32);
}

.czf-404__acts {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-12);
}

.czf-404__back {
  margin-top: var(--space-24);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-wide);
}

.czf-404__back[hidden] { display: none; }

.czf-404__back a {
  color: var(--c-ink-3);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.czf-404__back a:hover { color: var(--c-shield); }

@media (max-width: 767px) {
  .czf-404__panel { padding: var(--space-24); }
  .czf-404__panel::after { display: none; }
  .czf-404__acts .czf-btn { width: 100%; }
}
