/* ═══════════════════════════════════════════════════════════════
   Petro AI — the hero, the rotating claim, the deck, the reveals

   Loaded after the page's own stylesheet on every marketing page, and
   reading the tokens nova-home.css defines (--black, --teal, --white,
   --muted, --line) so there is one palette on the site.

   The hero is a split: the claim on the left, the film on the right.

   It was a full-screen scroll-driven expansion before this, and that was
   the wrong instrument. Opening a picture out under the scroll is a fine
   thing to do when the picture IS the subject; here the film is
   illustration and the claim is the subject, and putting the claim inside
   a picture that had to be scrolled open buried the sentence a visitor
   came to read. Side by side, both are legible in the first second.
   ═══════════════════════════════════════════════════════════════ */

.hero-split{
  position:relative;
  padding:clamp(56px,7vw,104px) 0 clamp(64px,8vw,116px);
  background:
    radial-gradient(120% 90% at 78% 8%, rgba(0,150,136,.13) 0%, transparent 62%),
    var(--black,#020607);
  overflow:hidden;
}

/* ── the ratio ──
   0.85fr against 1fr: roughly 46 to 54, in the film's favour.

   The reasoning, since it was asked for. The film is what makes somebody
   stop, so it takes the larger half. But the claim needs a measure it can
   actually be set in — at 46% of a 1240px page that is about 540px, which
   holds a 54px headline over two lines with a decent rag and a lede at a
   comfortable sixty characters. Narrower and the headline starts breaking
   in the wrong places; wider and the film stops being what you look at
   first. */
.hero-split-grid{
  display:grid;
  grid-template-columns:minmax(0,.85fr) minmax(0,1fr);
  align-items:center;
  gap:clamp(32px,4.5vw,72px);
}

.hero-split-copy{ min-width:0; }

/* ── the tag ──
   This was a soft teal bubble with a glowing, pulsing dot and a sentence
   set in title case. That combination is the house style of every AI
   landing page published in the last two years, which is exactly why it
   read as decoration rather than as a statement.

   The guidelines have an answer already: tags are small pills with a soft
   tint, and captions are Inter at 12/16. So it keeps the pill and takes
   the brand's caption treatment — uppercase, bold, generously tracked —
   and loses the glow. It now looks like a label on a product rather than
   a badge on a demo. */
.hero-eyebrow{
  display:inline-flex; align-items:center; gap:9px;
  margin:0 0 22px; padding:7px 13px;
  border:1px solid rgba(0,150,136,.42); border-radius:8px;
  background:rgba(0,150,136,.11);
  color:var(--teal-bright,#19B8A8);
  font-size:11.5px; line-height:16px; font-weight:700;
  letter-spacing:.13em; text-transform:uppercase;
}
.hero-eyebrow i{
  width:6px; height:6px; border-radius:2px;
  background:var(--teal-bright,#19B8A8);
  flex:none;
}

.hero-split h1{
  margin:0 0 20px;
  font-size:clamp(34px,4.4vw,58px);
  line-height:1.04; letter-spacing:-.032em; font-weight:700;
  color:var(--white,#F7F8FA);
}
.hero-split-lede{
  margin:0; max-width:52ch;
  color:var(--cloud,#E5E7EB); font-size:clamp(15px,1.35vw,18px); line-height:1.66;
}
.hero-actions{
  display:flex; flex-wrap:wrap; gap:12px;
  margin-top:28px;
}

/* ── the three proof points ──
   A term and its answer, which is what they are, rather than three more
   paragraphs. */
/* Three columns, not a wrapping row. As a flex row the third point fell
   to a second line on its own, which reads as one of them being an
   afterthought rather than as three of a kind. */
.hero-proof-list{
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:14px 22px;
  margin:30px 0 0; padding:20px 0 0;
  border-top:1px solid rgba(229,231,235,.16);
}
.hero-proof-list dt{
  color:var(--white,#F7F8FA);
  font-size:13.5px; font-weight:700; letter-spacing:-.01em;
}
.hero-proof-list dd{
  margin:3px 0 0;
  color:var(--muted,#9CA8B4); font-size:12.5px; line-height:1.45;
}

/* ── the film ── */
.hero-film{ margin:0; min-width:0; }
.hero-film-frame{
  position:relative;
  border-radius:18px;
  overflow:hidden;
  border:1px solid rgba(229,231,235,.14);
  background:var(--black,#020607);
  box-shadow:0 30px 90px -28px rgba(0,0,0,.95), 0 0 0 1px rgba(0,0,0,.7);
  /* Reserves the shape before a byte of video has arrived, so the column
     does not jolt taller the moment it loads. */
  aspect-ratio:16 / 9;
}
.hero-film-frame video{
  width:100%; height:100%;
  object-fit:cover; display:block;
}

/* A soft darkening top and bottom so the film sits in the page rather than
   being pasted on to it. Light, because nothing is read over this one. */
.hero-film-frame::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(180deg, rgba(2,6,7,.28) 0%, rgba(2,6,7,0) 30%, rgba(2,6,7,.34) 100%);
}

.hero-film-tag{
  position:absolute; left:12px; bottom:12px; z-index:2;
  display:inline-flex; align-items:center; gap:8px;
  padding:6px 11px; border-radius:8px;
  background:rgba(2,6,7,.74); border:1px solid rgba(229,231,235,.16);
  backdrop-filter:blur(8px);
  color:var(--cloud,#E5E7EB);
  font-size:10.5px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
}
.hero-film-tag i{
  width:6px; height:6px; border-radius:2px;
  background:var(--teal-bright,#19B8A8); flex:none;
}

.hero-film figcaption{
  display:flex; align-items:center; justify-content:space-between; gap:18px;
  margin-top:12px;
}
.hero-film figcaption p{
  margin:0; color:var(--muted,#9CA8B4); font-size:11.5px; line-height:1.55;
}

/* ── the pause control ──
   The film loops on its own, which makes it continuous motion nobody asked
   for, and continuous motion has to be stoppable. This is not decoration:
   it is the difference between a page somebody with a vestibular disorder
   can read and one they have to leave. */
.hero-film-toggle{
  flex:none;
  padding:6px 12px; border-radius:8px;
  background:transparent;
  border:1px solid rgba(229,231,235,.24);
  color:var(--cloud,#E5E7EB);
  font:700 10.5px/1.4 inherit; letter-spacing:.09em; text-transform:uppercase;
  cursor:pointer;
  transition:background .2s var(--ease,cubic-bezier(.16,1,.3,1)),
             border-color .2s var(--ease,cubic-bezier(.16,1,.3,1));
}
.hero-film-toggle:hover{ background:rgba(229,231,235,.09); border-color:rgba(229,231,235,.4); }
.hero-film-toggle:focus-visible{ outline:2px solid var(--teal-bright,#19B8A8); outline-offset:2px; }

/* Until the script has taken charge of the film there is nothing behind
   this button: the markup's own autoplay/loop attributes are what is
   playing, and a button that does not stop them is worse than no button
   at all. The script stamps data-film-state as soon as it is listening. */
.hero-film:not([data-film-state]) .hero-film-toggle{ display:none; }

@media (max-width:900px){
  .hero-split-grid{ grid-template-columns:1fr; gap:34px; }
  .hero-split h1{ font-size:clamp(31px,7.6vw,44px); }
  .hero-actions{ flex-direction:column; align-items:stretch; }
  .hero-proof-list{ grid-template-columns:1fr 1fr; gap:12px 22px; }
}

/* ═══════════════ the rotating claim ═══════════════
   "Make your petrol station ___", where the blank changes. One claim said
   several ways, so a visitor who reads for four seconds learns four things
   rather than one.

   A fixed slot with the words stacked inside it: the current one at rest,
   the ones already said pushed up and out, the ones still to come waiting
   below. That vertical roll is the whole trick.

   The slot reserves the width of the LONGEST word with an invisible copy
   of it in normal flow — otherwise everything after the slot jumps
   sideways every couple of seconds. */
.rotator{
  position:relative; display:inline-grid; vertical-align:top;
  overflow:hidden;
  padding-block:.1em;   /* room for descenders and the spring's overshoot */
}
/* In the same cell as the words, said explicitly.

   Without this the gauge is AUTO-placed, and auto-placement runs after the
   explicitly-positioned items — so it found row 1 taken, dropped itself
   into row 2, and doubled the height of the slot. That was the dead band
   under the headline: 132px of grid where 72px of type belonged. */
.rotator-gauge{ grid-area:1/1; visibility:hidden; pointer-events:none; }
.rotator [data-word]{
  grid-area:1/1;
  white-space:nowrap;
  background:linear-gradient(100deg,var(--teal-bright,#19B8A8),var(--teal,#009688));
  -webkit-background-clip:text; background-clip:text; color:transparent;
  /* A spring that overshoots slightly and settles — the same feel as the
     stiffness/damping pair this is borrowed from, written as a curve. */
  transition:transform .62s cubic-bezier(.22,1.28,.36,1), opacity .42s ease;
}
.rotator [data-word][data-state="current"]{ transform:none; opacity:1; }
.rotator [data-word][data-state="gone"]{ transform:translateY(-140%); opacity:0; }
.rotator [data-word][data-state="waiting"]{ transform:translateY(140%); opacity:0; }

/* Before the script runs every word shares one cell and they would print
   on top of each other. Show the first, hide the rest, so the sentence
   reads correctly with no JavaScript at all. */
.rotator:not([data-rotator-ready="true"]) [data-word]{ opacity:0; }
.rotator:not([data-rotator-ready="true"]) [data-word]:first-of-type{ opacity:1; }

/* ═══════════════ the deck ═══════════════

   Its own section, with room and no clipping. */
.deck-section{
  padding:clamp(72px,9vw,130px) 0 0;
  border-bottom:1px solid var(--line,rgba(229,231,235,.14));
}
.deck-head{ max-width:940px; margin:0 auto; text-align:center; }
.deck-head h2{
  margin:10px 0 0; font-size:clamp(30px,3.6vw,50px);
  line-height:1.07; letter-spacing:-.03em; font-weight:700;
  color:var(--white,#F7F8FA);
}
.deck-head > p:last-child{
  margin:20px auto 0; max-width:620px;
  color:var(--muted,#9CA8B4); font-size:16px; line-height:1.65;
}

/* Dashboard captures stacked and skewed like cards dealt on a table, each
   lifting when it is pointed at or focused. Three screenshots side by side
   are three things to compare; a deck is one thing with more behind it,
   which is what a reader can actually take in. */
.deck{
  display:grid;
  grid-template-areas:'stack';
  place-items:center;
  /* Room for the fan.

     Every card sits in the same grid cell, so the grid is only as tall as
     ONE of them — and a transform is not counted when the browser works out
     how much room a grid needs. Without a reserve the deck sits straight on
     top of whatever follows it.

     The reserve is written by the script from the number of cards, because
     a fixed one is only ever right for the deck it was measured against:
     250px held three cards and was 38px short of four, so the link under
     the homepage deck went back under a card. */
  padding:40px 0 var(--deck-reserve, 260px);
}
.deck > *{ grid-area:stack; }

.deck-card{
  --deck-i:0;
  position:relative;
  width:min(560px, 78vw);
  margin:0;
  padding:8px;
  border:1px solid var(--line-2,rgba(229,231,235,.22));
  border-radius:16px;
  background:linear-gradient(180deg,#16242C,#0B1319);
  box-shadow:0 0 0 1px rgba(0,0,0,.85), 0 26px 60px -22px rgba(0,0,0,.95);
  cursor:pointer;
  /* Stated rather than inherited from DOM order: a skewed, translated card
     does not occupy the box its source position suggests. */
  z-index:calc(var(--deck-i) + 1);
  /* The offsets have to be a large fraction of the card's own height, or
     the card in front covers the one behind completely and there is
     nothing left to point at. The effect this comes from uses cards 352 by
     144 — short and wide — where a 40px drop exposes a quarter of each.
     These are screenshots at 16:10 and about 350 tall, so the same 40px
     exposed a tenth and the top card swallowed every target beneath it. */
  transform:
    translate(calc(var(--deck-i) * 72px), calc(var(--deck-i) * 96px))
    skewY(-8deg);
  filter:grayscale(1) brightness(.72);
  transition:transform .7s var(--ease,cubic-bezier(.16,1,.3,1)),
             filter .7s var(--ease,cubic-bezier(.16,1,.3,1)),
             box-shadow .7s var(--ease,cubic-bezier(.16,1,.3,1));
  will-change:transform;
}
.deck-card img{ display:block; width:100%; height:auto; border-radius:9px; }

.deck-caption{
  display:flex; align-items:center; gap:9px;
  padding:11px 4px 2px;
  color:var(--muted,#9CA8B4); font-size:12px;
}
.deck-caption i{
  width:7px; height:7px; border-radius:2px;
  background:var(--teal-bright,#19B8A8); flex:none;
}

/* The one being looked at comes forward, straightens and regains its
   colour. Everything behind it stays where it is. */
.deck-card:hover, .deck-card:focus-visible{
  transform:
    translate(calc(var(--deck-i) * 72px), calc(var(--deck-i) * 96px - 30px))
    skewY(-2deg) scale(1.03);
  filter:none;
  box-shadow:0 0 0 1px rgba(25,184,168,.4), 0 40px 90px -26px rgba(0,0,0,.98);
  z-index:9;
  outline:none;
}
.deck-card:focus-visible{ box-shadow:0 0 0 3px rgba(25,184,168,.6), 0 40px 90px -26px rgba(0,0,0,.98); }

/* Until the script has indexed the cards they would all sit at offset zero,
   exactly on top of one another, and the deck would look like one card. */
.deck:not([data-deck-ready="true"]) .deck-card{ filter:none; }
.deck:not([data-deck-ready="true"]) .deck-card + .deck-card{ display:none; }

/* A deck is a pointing gesture and a phone has no pointer. On a small
   screen the captures stack plainly, in colour, one under another — which
   is what somebody on a phone actually wants. */
@media (max-width:860px){
  .deck{ grid-template-areas:none; gap:26px; padding:24px 0 50px; }
  .deck > *{ grid-area:auto; }
  .deck-card{ width:100%; transform:none; filter:none; }
  .deck-card:hover, .deck-card:focus-visible{ transform:none; }
}

/* ═══════════════ reveals ═══════════════
   One class, driven by an observer, used by every section on the site.
   Transform and opacity only: both composite, so a page full of these
   still scrolls at frame rate on a mid-range phone. */
[data-reveal]{
  opacity:0;
  transform:translateY(22px);
  transition:opacity .7s var(--ease,cubic-bezier(.16,1,.3,1)),
             transform .7s var(--ease,cubic-bezier(.16,1,.3,1));
  transition-delay:var(--reveal-delay,0ms);
}
[data-reveal][data-shown="true"]{ opacity:1; transform:none; }

/* ═══════════════ less movement, honestly ═══════════════
   Someone who asked their system for less movement gets the film held on
   its poster frame, the claim on its first word, and everything already in
   place. Nothing is hidden from them; it simply does not move. */
@media (prefers-reduced-motion:reduce){
  .rotator [data-word]{ transition:none; }
  .deck-card{ transition:none; }
  [data-reveal]{ opacity:1; transform:none; transition:none; }
}

/* ═══════════════ the tilt ═══════════════
   The capture lies back and stands up as the reader scrolls to it, like a
   screen being raised to face you.

   These are the numbers it had when it worked: twenty degrees of lean, a
   1120px frame, a section 80rem tall so the movement has a long deliberate
   run, and a scale that starts ABOVE one and settles — the card arrives
   slightly larger than life and eases down to size, which is what made it
   feel like something being presented rather than something growing.

   A rebuild of this by eye used eighteen degrees, a 1080px frame, a scale
   starting below one and a section a single viewport tall. Every one of
   those was a little smaller and a little shorter, and together they made
   it unremarkable. The lesson is not subtle: an effect is its numbers.

   The rotation is on the card and the perspective is on the parent, which
   is the only arrangement that gives real foreshortening — perspective on
   the same element as the transform flattens it into a shear. */
.tilt-section{
  /* Declared HERE, on the section, and not on the card.

     The script writes these on the section and lets them inherit. A card
     declaring its own copy would resolve from itself and beat the inherited
     value in every stylesheet at any source order — which is precisely how
     the NOVA panel survived a whole-dashboard conversion to white, recorded
     in CLAUDE.md. Same trap, and it would leave the capture leaning for
     ever. */
  --tilt-rotate:20deg;
  --tilt-scale:1.05;
  --tilt-title-y:0px;
  min-height:80rem;
  display:flex; align-items:center;
  padding:80px 0 130px;
  overflow:clip;
  background:var(--black,#020607);
  border-bottom:1px solid var(--line,rgba(229,231,235,.14));
}
.tilt-stage{ perspective:1000px; width:100%; }

.tilt-head{
  position:relative; z-index:2;
  max-width:940px; margin:0 auto;
  text-align:center;
  transform:translateY(var(--tilt-title-y));
  will-change:transform;
}
.tilt-head h2{
  margin:8px 0 0;
  font-size:clamp(40px,5.6vw,78px);
  line-height:1.02; letter-spacing:-.03em; font-weight:700;
  color:var(--white,#F7F8FA);
}
.tilt-head p:last-child{
  margin:24px auto 0; max-width:620px;
  color:var(--muted,#9CA8B4); font-size:17px; line-height:1.6;
}

.tilt-card{
  position:relative; z-index:1;
  max-width:1120px;
  /* Pulled up under the heading, so the two overlap slightly and read as
     one object rather than as a title with a picture beneath it. */
  margin:-18px auto 0;
  padding:10px;
  background:#10181D;
  border:1px solid rgba(229,231,235,.38);
  box-shadow:
    0 0 0 1px rgba(0,0,0,.9),
    0 18px 35px rgba(0,0,0,.55),
    0 70px 90px rgba(0,0,0,.45);
  transform-origin:center top;
  transform:rotateX(var(--tilt-rotate)) scale(var(--tilt-scale));
  will-change:transform;
}
.tilt-card img{ display:block; width:100%; height:auto; }
.tilt-card figcaption{
  display:flex; justify-content:space-between; align-items:center; gap:20px;
  padding:7px 5px 16px;
  color:var(--muted,#9CA8B4); font-size:11px;
}
.tilt-card figcaption span{ display:flex; align-items:center; gap:8px; }
.tilt-card figcaption i{
  width:7px; height:7px; border-radius:50%;
  background:var(--teal-bright,#19B8A8); flex:none;
}
.tilt-card figcaption a{
  color:var(--cloud,#E5E7EB); font-weight:600;
  border-bottom:1px solid rgba(229,231,235,.32);
}

/* Before the script measures anything, and for anybody who asked for less
   movement, the screen faces front at its resting size. A capture frozen
   half-tilted looks like a rendering fault rather than an effect. */
.tilt-section:not([data-tilt-ready="true"]){
  --tilt-rotate:0deg; --tilt-scale:1; --tilt-title-y:0px;
}
@media (prefers-reduced-motion:reduce){
  .tilt-section{ --tilt-rotate:0deg; --tilt-scale:1; --tilt-title-y:0px; }
  .tilt-card, .tilt-head{ transform:none !important; }
}

@media (max-width:860px){
  /* A phone cannot carry a 1280px section without it feeling like a
     corridor, and at that width the card is already nearly full-bleed —
     so it starts smaller and grows, rather than starting oversized. */
  .tilt-section{ min-height:50rem; --tilt-scale:.78; padding:72px 0; }
  .tilt-head h2{ font-size:clamp(32px,8vw,48px); }
}
