/* ─────────────────────────────────────────────────────────────────────────────
   ptech-home.css — Portillo Technologies overrides for the homepage.

   The homepage is a Webflow export cloned from cinetica.studio. Editing that
   vendored stylesheet directly makes every future diff unreadable, so brand
   changes live HERE and load after it. Load order is the whole mechanism: this
   file wins on equal specificity. Keep it that way.

   Palette is the brand kit's, not Cinética's:
   Brands/portillo-technologies/brand-kit/tokens.css
   Green is the only chromatic moment and it has to MEAN something — active,
   live, "this is the path." Never a decorative fill. (guidelines.md §4)
   ───────────────────────────────────────────────────────────────────────────── */

:root {
  --ptech-ink: #08090A;
  --ptech-ink-2: #0D0E10;
  --ptech-ink-3: #131517;
  --ptech-bone: #ECECE8;
  --ptech-bone-dim: #93958F;
  --ptech-hair: rgba(236, 236, 232, 0.10);
  --ptech-green: #1B8A5A;
  --ptech-green-glow: #3EE08C;
  --ptech-ease: cubic-bezier(0.32, 0.72, 0, 1);
}

/* ── Services rows ────────────────────────────────────────────────────────────
   Was: a 10%-wide photo thumbnail that faded in under the cursor. It pulled the
   eye off the words and the stock imagery said nothing about the service.

   Now: the row itself responds. A green rule draws in from the left, the row
   lifts onto a raised surface, the sparkle mark turns green, and the heading
   steps toward the reader. All transform/opacity, so it stays on the compositor.

   .services-tab__item carries opacity:.2 from the carousel logic — the active
   panel is animated to 1 by Webflow IX2. Never set opacity on the row itself
   here or the carousel's own state fights this file and the row flickers.
   ───────────────────────────────────────────────────────────────────────────── */

.services-tab__item .service-link {
  isolation: isolate;
  transition: background-color 0.5s var(--ptech-ease);
}

/* the raised surface, painted behind the content */
.services-tab__item .service-link::before {
  content: "";
  position: absolute;
  inset: 0 calc(var(--gap-reg, 1rem) * -0.5);
  z-index: 0;
  background: linear-gradient(
    90deg,
    rgba(27, 138, 90, 0.10) 0%,
    rgba(19, 21, 23, 0.55) 35%,
    rgba(19, 21, 23, 0) 100%
  );
  opacity: 0;
  transition: opacity 0.55s var(--ptech-ease);
  pointer-events: none;
}

.services-tab__item .service-link:hover::before,
.services-tab__item .service-link:focus-visible::before {
  opacity: 1;
}

/* the green rule: draws left to right along the row's existing hairline */
.services-tab__item .services-tab__item-border {
  transform-origin: left center;
  transition: background-color 0.5s var(--ptech-ease),
              transform 0.6s var(--ptech-ease);
}

.services-tab__item .service-link:hover ~ .services-tab__item-border,
.services-tab__item .service-link:hover .services-tab__item-border {
  background-color: var(--ptech-green-glow);
  transform: scaleY(2);
}

/* the sparkle mark: green and rotating on approach */
.services-tab__item .services-tab__svg-wrapper {
  color: var(--ptech-bone-dim);
  transition: color 0.5s var(--ptech-ease), transform 0.7s var(--ptech-ease);
}

.services-tab__item .service-link:hover .services-tab__svg-wrapper,
.services-tab__item .service-link:focus-visible .services-tab__svg-wrapper {
  color: var(--ptech-green-glow);
  transform: rotate(90deg) scale(1.15);
}

/* the words step forward */
.services-tab__item .services-item__inner {
  transition: transform 0.6s var(--ptech-ease);
}

.services-tab__item .service-link:hover .services-item__inner,
.services-tab__item .service-link:focus-visible .services-item__inner {
  transform: translateX(0.6em);
}

.services-tab__item .services-item__inner.is--right {
  transition: transform 0.6s var(--ptech-ease);
}

.services-tab__item .service-link:hover .services-item__inner.is--right {
  transform: translateX(-0.6em);
}

.services-tab__item .services-tab__item-heading {
  transition: color 0.5s var(--ptech-ease);
}

.services-tab__item .service-link:hover .services-tab__item-heading {
  color: var(--ptech-bone);
}

/* Someone who asked for less motion gets the color shift and nothing that moves. */
@media (prefers-reduced-motion: reduce) {
  .services-tab__item .services-tab__svg-wrapper,
  .services-tab__item .services-item__inner,
  .services-tab__item .services-item__inner.is--right,
  .services-tab__item .services-tab__item-border {
    transition: color 0.3s linear, background-color 0.3s linear;
    transform: none !important;
  }
}

/* ── Page rows (services, process, and the sub-pages) ─────────────────────────
   The homepage's own services rows live inside a draggable carousel, so their
   markup carries carousel state we do not want on a static page. These are the
   same visual language — hairline-separated rows, big heading, quiet body — with
   none of the carousel machinery.
   ───────────────────────────────────────────────────────────────────────────── */

.ptech-rows {
  margin-top: 4em;
  border-top: 1px solid var(--ptech-hair);
}

.ptech-row {
  padding: 2.2em 0;
  border-bottom: 1px solid var(--ptech-hair);
  position: relative;
  transition: background-color 0.5s var(--ptech-ease);
}

.ptech-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--ptech-green-glow);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform 0.55s var(--ptech-ease);
}

.ptech-row:hover::before { transform: scaleY(1); }

.ptech-row__h {
  text-transform: uppercase;
  font-size: 1.9em;
  margin: 0 0 0.45em;
  letter-spacing: -0.01em;
}

.ptech-row p { margin: 0; max-width: 46em; }

.ptech-row__link {
  display: inline-block;
  margin-top: 1.1em;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ptech-green-glow);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.4s var(--ptech-ease);
}

.ptech-row__link:hover { border-bottom-color: var(--ptech-green-glow); }

@media (max-width: 767px) {
  .ptech-row__h { font-size: 1.5em; }
  .ptech-rows { margin-top: 2.4em; }
}

@media (prefers-reduced-motion: reduce) {
  .ptech-row::before { transition: none; }
}

/* ── Offer rows ───────────────────────────────────────────────────────────────
   The "(Where to start)" section was the one block on the homepage written
   against its own hand-rolled classes (.offer-card, .offer-grid) instead of the
   design system. That is why it read as a different site mid-scroll — Jason's
   note, 09-04. It now uses the same section chain and the same rows as
   everything else; only the price label is new.
   ───────────────────────────────────────────────────────────────────────────── */

.ptech-rows--offer { margin-top: 3.4em; }

.ptech-row__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5em;
  flex-wrap: wrap;
  margin-bottom: 0.5em;
}

.ptech-row__head .ptech-row__h { margin: 0; }

.ptech-row__price {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ptech-bone-dim);
  white-space: nowrap;
}

/* Free is the front door, so it is the one thing here allowed to be green. */
.ptech-row__price.is--free { color: var(--ptech-green-glow); }

@media (max-width: 600px) {
  .ptech-row__head { gap: 0.3em; }
  .ptech-row__price { white-space: normal; }
}

/* ── ptech-section: the section wrapper for every page that is not the homepage ──
   .about-section cannot be reused off the homepage. The vendored export gives it
   `margin-top: -150vh` so it docks underneath the homepage hero, plus a white
   background and black text for Cinética's light theme. On a page with no hero,
   every section pulls up 150vh and they stack on top of each other above the
   fold: the document collapses to ~720px tall and the page renders black with
   only the header visible. That is exactly what happened on the first build, and
   a screenshot caught it after an element-visibility check did not — the sections
   were "visible", just at negative coordinates.

   This class is the same section, without the docking behaviour.
   ───────────────────────────────────────────────────────────────────────────── */

.ptech-section {
  position: relative;
  z-index: 6;
  width: 100%;
  background-color: var(--ptech-ink);
  color: var(--ptech-bone);
}

/* First section on a page sits under the fixed header, so it needs the clearance
   the homepage gets from its hero. */
main > .ptech-section:first-child { padding-top: 6vh; }

/* ── The button ───────────────────────────────────────────────────────────────
   .offer-btn was defined only inside index.html's inline <style>, so no other
   page could reach it. Three rebuilt pages independently re-implemented it, and
   a fourth (ai-pilot-autopsy) invented a different-looking one because, from a
   sub-page's point of view, no shared button existed. It lives here now.

   Bone on ink, pill-shaped. It is NOT green: green marks the one path forward
   in a view, and a page whose every button is green has marked nothing.
   ───────────────────────────────────────────────────────────────────────────── */

.offer-btn {
  display: inline-block;
  text-decoration: none;
  background: var(--ptech-bone);
  color: var(--ptech-ink);
  border: 1px solid var(--ptech-bone);
  border-radius: 999px;
  padding: 0.95rem 2.2rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: transform 0.25s ease;
}

.offer-btn:hover,
.offer-btn:focus-visible { transform: scale(0.97); }

.offer-btn.is-ghost {
  background: transparent;
  color: var(--ptech-bone);
  border-color: rgba(236, 236, 232, 0.28);
}

.offer-btn.is-ghost:hover,
.offer-btn.is-ghost:focus-visible { border-color: var(--ptech-bone); }

.offer-cta {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: center;
}

@media (prefers-reduced-motion: reduce) {
  .offer-btn:hover, .offer-btn:focus-visible { transform: none; }
}

/* Rows are a reading measure, not the full container width, and they sit centred under
   the centred section header. Left-flushed body copy beneath a centred heading was the
   imbalance in Jason's 09-05 screenshot. */
.ptech-rows { max-width: 62em; margin-inline: auto; }

/* ── Section headings on sub-pages ────────────────────────────────────────────
   .about-heading is 7em, sized for the homepage's short headings ("One team,
   working two problems at once"). The sub-pages carry full question headings —
   "What does an AI consultant in Orange County actually do?" — and at 7em a
   question like that fills the entire viewport before a word of the answer is
   visible. Same voice, scaled to the sentence it has to hold.

   Long headings shrink further so the question and the start of its answer can
   share a screen, which is the whole point of leading with the question.
   ───────────────────────────────────────────────────────────────────────────── */

.ptech-section .about-heading {
  font-size: clamp(2rem, 4.6vw, 4.2em);
  letter-spacing: -0.015em;
  line-height: 1.02;
  max-width: 18ch;
  margin: 0 auto;
  display: block;
  text-wrap: balance;
}

.form-note {
  margin: 0.85em 0 0;
  font-size: 0.82em;
  line-height: 1.4;
  color: var(--ptech-bone-dim);
  text-align: center;
}

@media (max-width: 479px) {
  .form .field.w-input,
  .contact-form__input {
    font-size: 16px;
  }
}

@media (max-width: 767px) {
  .ptech-section .about-heading { font-size: clamp(1.75rem, 7.5vw, 2.4rem); max-width: 16ch; }
}

/* The lede and the answer-first paragraph sit under a centred heading, so they
   are centred blocks of left-read text — not left-flushed against a wide container. */
.ptech-section .txt-align-center { margin-inline: auto; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10000;
  background: var(--ptech-bone);
  color: var(--ptech-ink);
  padding: 0.6rem 1rem;
}
.skip-link:focus {
  left: 0.75rem;
  top: 0.75rem;
}

/* ── Horizontal words rail ────────────────────────────────────────────────────
   Sticky chapter: "AI that disappears into the work." Letters form on a
   baseline as they enter, dissolve as they leave. Edge masks keep the clip
   from reading as a hard cut. --rail is written by the scroll trigger.
   ───────────────────────────────────────────────────────────────────────────── */

.horizontal-words {
  background: var(--ptech-ink);
  --rail: 0;
}

.horizontal-words_content {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0%,
    #000 10%,
    #000 90%,
    transparent 100%
  );
  mask-image: linear-gradient(
    90deg,
    transparent 0%,
    #000 10%,
    #000 90%,
    transparent 100%
  );
}

.horizontal-words_content::after {
  content: "";
  position: absolute;
  left: 4em;
  right: 4em;
  bottom: 2.2em;
  height: 1px;
  background: var(--ptech-hair);
  transform: scaleX(var(--rail));
  transform-origin: left center;
  pointer-events: none;
}

.horizontal-words_wrapper {
  will-change: transform;
}

.horizontal-words_text .letter {
  display: inline-block;
  will-change: transform, opacity;
}

.horizontal-words_svg {
  color: var(--ptech-bone);
  transform-origin: 50% 50%;
}

@media (max-width: 767px) {
  .horizontal-words_content::after {
    left: 1.4em;
    right: 1.4em;
    bottom: 1.4em;
  }
}

@media (prefers-reduced-motion: reduce) {
  .horizontal-words_height { height: 100vh; }
  .horizontal-words_wrapper {
    margin-left: 1.5em;
    margin-right: 1.5em;
    transform: none !important;
    justify-content: center;
  }
  .horizontal-words_text { white-space: normal; }
  .horizontal-words_content {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .horizontal-words_content::after { display: none; }
}
