/* ==========================================================================
   GR Auto Center Inc — v3 delta stylesheet
   Loaded ONLY on the v3 build, after styles.css and styles-v2.css. v3 is v2
   in every respect except the hero: instead of one static photo, three to
   five photos crossfade on a 6-seconds-per-slide clock. Pure CSS — no
   JavaScript, so the rotation (and the reduced-motion fallback) works with
   JS disabled. Do not duplicate rules that already live in styles.css or
   styles-v2.css.

   Nothing in this file is bound to a slide's position except the things that
   genuinely are positional — which slide paints first, and which dot is
   which. Framing and the clock both come from the markup that src/photos.py
   generates:

     .hero__slides.hs-N   how many slides there are  ->  --n
     .hero__slide         style="--i:K"              ->  its turn in the cycle
                          plus --focus / --focus-sm / --focus-lg

   That is the whole point of the file: reordering the photographs in
   src/photos.json used to hand slide 2's crop to whatever photo moved into
   second place. Now the crop travels with the photograph.
   ========================================================================== */

/* --- Slide stack: fills .hero__media exactly (absolute, inset:0), so the
   slideshow never changes the hero's height — .hero__media already governs
   that, on both the desktop absolute-fill layout and v2's mobile
   aspect-ratio:4/3 box. --- */
.hero__slides{position:absolute;inset:0}
.hero__slide{position:absolute;inset:0;opacity:0}
.hero__slide img{width:100%;height:100%;object-fit:cover}

/* Slide 1 must be visible at first paint — before the animation's own 0%
   keyframe (opacity:0) has had a chance to apply — so there's never a blank
   hero flash. The animation (below) takes over this value once it runs.
   This one is legitimately positional: "first" is a paint order, not a
   property of any particular photograph. */
.hero__slide:nth-child(1){opacity:1}

/* The base kenburns animation targets ".hero__media img" — every slide's
   <img> matches that selector too, so it has to be switched off here or the
   photo underneath the crossfade/zoom would double-animate. */
.hero__slides img{animation:none}

/* --- Framing, per photograph, never per position. The fallbacks restate the
   values the photo would otherwise inherit: styles.css:291-292 (center 30%,
   center 40% from 900px) and styles.v2.css:16 (center 55% under 720px), so a
   slide with no framing set renders exactly as it did before this file
   existed. --- */
.hero__slide img{object-position:var(--focus,center 30%)}
@media (max-width:719px){
  .hero__slide img{object-position:var(--focus-sm,var(--focus,center 55%))}
}
@media (min-width:900px){
  .hero__slide img{object-position:var(--focus-lg,var(--focus,center 40%))}
}

/* --- Crossfade + slow zoom, on a clock that follows the folder. Every slide
   holds for 6s, so N slides make an N x 6s cycle and slide K starts at K x 6s.
   Opacity and scale live in the same keyframes so the zoom reads as a slow
   pan across each slide's visible window, not a hard cut. Scale animates on
   the <picture class="hero__slide"> box itself (not the <img>) — cheap, and
   it avoids fighting the disabled kenburns rule on the <img>.

   Three keyframe sets rather than one, because a keyframe percentage cannot
   be computed from a custom property. Each holds its slide for one Nth of
   the cycle: N=3 -> 33.333%, N=4 -> 25%, N=5 -> 20%. --- */
.hs-3{--n:3}
.hs-4{--n:4}
.hs-5{--n:5}

@keyframes heroFade3{
  0%{opacity:0;transform:scale(1.03)}
  2%{opacity:1;transform:scale(1.03)}
  31%{opacity:1;transform:scale(1.09)}
  33.333%{opacity:0;transform:scale(1.09)}
  100%{opacity:0;transform:scale(1.09)}
}
@keyframes heroFade4{
  0%{opacity:0;transform:scale(1.03)}
  1.5%{opacity:1;transform:scale(1.03)}
  23%{opacity:1;transform:scale(1.09)}
  25%{opacity:0;transform:scale(1.09)}
  100%{opacity:0;transform:scale(1.09)}
}
@keyframes heroFade5{
  0%{opacity:0;transform:scale(1.03)}
  1.5%{opacity:1;transform:scale(1.03)}
  18%{opacity:1;transform:scale(1.09)}
  20%{opacity:0;transform:scale(1.09)}
  100%{opacity:0;transform:scale(1.09)}
}
@keyframes heroDot3{
  0%{background:rgba(244,239,227,.3)}
  2%{background:#E9C44A}
  31%{background:#E9C44A}
  33.333%{background:rgba(244,239,227,.3)}
  100%{background:rgba(244,239,227,.3)}
}
@keyframes heroDot4{
  0%{background:rgba(244,239,227,.3)}
  1.5%{background:#E9C44A}
  23%{background:#E9C44A}
  25%{background:rgba(244,239,227,.3)}
  100%{background:rgba(244,239,227,.3)}
}
@keyframes heroDot5{
  0%{background:rgba(244,239,227,.3)}
  1.5%{background:#E9C44A}
  18%{background:#E9C44A}
  20%{background:rgba(244,239,227,.3)}
  100%{background:rgba(244,239,227,.3)}
}

@media (prefers-reduced-motion:no-preference){
  .hero__slide{
    animation-duration:calc(var(--n,4) * 6s);
    animation-timing-function:linear;
    animation-iteration-count:infinite;
    animation-delay:calc(var(--i,0) * 6s);
    will-change:opacity,transform;
  }
  .hs-3 .hero__slide{animation-name:heroFade3}
  .hs-4 .hero__slide{animation-name:heroFade4}
  .hs-5 .hero__slide{animation-name:heroFade5}

  .hero__dots i{
    animation-duration:calc(var(--n,4) * 6s);
    animation-timing-function:linear;
    animation-iteration-count:infinite;
  }
  .hero__dots.hs-3 i{animation-name:heroDot3}
  .hero__dots.hs-4 i{animation-name:heroDot4}
  .hero__dots.hs-5 i{animation-name:heroDot5}

  /* A dot's position IS its identity — there is nothing else to key on. */
  .hero__dots i:nth-child(1){animation-delay:0s}
  .hero__dots i:nth-child(2){animation-delay:6s}
  .hero__dots i:nth-child(3){animation-delay:12s}
  .hero__dots i:nth-child(4){animation-delay:18s}
  .hero__dots i:nth-child(5){animation-delay:24s}
}

/* --- Dots: bottom-right of the hero, on the same clock as the slides. One
   <i> per slide, emitted by {{#each hero_slides}}, so a fifth photograph can
   no longer end up with no dot. --- */
.hero__dots{
  position:absolute;z-index:2;pointer-events:none;
  right:clamp(14px,4vw,44px);bottom:clamp(14px,4vw,28px);
  display:flex;gap:8px;
}
.hero__dots i{
  display:block;width:6px;height:6px;border-radius:50%;
  background:rgba(244,239,227,.3);
}
.hero__dots i:nth-child(1){background:#E9C44A}
@media (max-width:479px){
  .hero__dots{display:none}
}

/* --- Reduced motion: no animation at all. Slide 1 stays put, the rest stay
   hidden, the first dot stays gold. --- */
@media (prefers-reduced-motion:reduce){
  .hero__slide{animation:none;opacity:0;transform:none}
  .hero__slide:nth-child(1){opacity:1}
  .hero__dots i{animation:none}
}

/* --- The shop's own artwork (src/artwork.py) -----------------------------
   Two pieces the owner had made and sent over: the sign card that carries
   his logo and service list, and the inspection flyer he hands out. Both are
   flat navy artwork with their own type already on them, so neither is ever
   stretched across a box and written over — the sign card is composed inside
   the hero as an object, and the flyer is a framed figure with a caption.

   Both are capped well below their natural 940px so they stay crisp on a 2x
   screen; `sizes` in the templates matches these caps, and if you change one
   change the other. --- */

/* --- The sign card, as the last slide of the hero rotation ---------------
   It is composed, not stretched, and that is the whole design of this block.
   Every other slide is a photograph: object-fit:cover across the full bleed,
   with the headline and the buttons laid over it. This one cannot be treated
   that way, for three reasons that all point the same direction.

   It is type. Covering a 16:9 hero would crop the logo off the top or the
   phone number off the bottom, and cropping a sign is vandalism. It is 940px
   wide — plenty for a card, nowhere near enough to stretch across a 1440px
   hero without going soft, and softness shows on lettering far more than on
   a photograph. And it already carries its own headline, so our headline on
   top of it would leave neither readable.

   So it sits inside the hero as an object: a lit sign on the wall, to the
   right of the copy on a desktop and above it on a phone. At the sizes below
   the source is never upscaled.

   If a print-resolution copy of this artwork ever turns up, a full-bleed
   treatment becomes possible and this block is what to revisit. */
.hero__slide--art{
  background:
    radial-gradient(76% 108% at 74% 34%,rgba(233,196,74,.20) 0%,rgba(233,196,74,0) 62%),
    linear-gradient(180deg,#150E29 0%,var(--ink) 52%,#150E29 100%);
}
.hero__slide--art img{
  /* Overrides .hero__slide img's cover-the-box rule from the top of this
     file. Sized in CSS pixels rather than by object-fit so the card cannot
     grow past the source's real resolution. */
  position:absolute;
  width:min(78vw,400px);height:auto;
  left:50%;top:44%;transform:translate(-50%,-50%);
  object-fit:contain;
  border-radius:var(--r);
  border:1px solid rgba(233,196,74,.5);
  box-shadow:0 22px 54px rgba(0,0,0,.5);
  /* .hero__scrim is painted above every slide and cannot be turned off for
     one of them, so the card is pre-lifted to land at roughly its own
     brightness once the scrim is over it. Photographs want the scrim; a sign
     that is already dark navy just goes muddy. */
  filter:brightness(1.75) saturate(1.3) contrast(1.08);
}
@media (min-width:720px){
  /* Desktop: the copy is bottom-left and the OPEN SUNDAYS stamp is top-right,
     so the card takes the right-hand column between them. */
  .hero__slide--art img{
    left:auto;right:clamp(24px,6vw,88px);
    top:52%;transform:translateY(-50%);
    width:min(42vw,540px);
  }
}
@media (max-width:719px){
  /* Phones. .hero__media is a poster box with the copy below it, and the
     OPEN SUNDAYS stamp is positioned against .hero — so on a phone it lands
     in the top-right of that box, on top of whichever slide is showing. The
     sign has to live UNDER it, not behind it.

     Three things make that tight instead of sloppy:

     1. The box is 1:1 here rather than v2's 4:3 — which is what v1 ran on
        phones, so the photographs are used to a tall crop and their
        --focus-sm values still apply. A 4:3 box left the sign either under
        the stamp or shrunk to 58vw with a slab of dead ink above it; a 7:6
        box only fit by shrinking the stamp to 80px, which the owner could
        not read. 1:1 holds a legible stamp AND the sign at real size.
     2. The stamp is 112px: big enough to read "24 HOURS TOWING" at arm's
        length, small enough to leave the sign the rest of the box.
     3. The sign paints ABOVE the box's own fade-to-ink. That ::after
        gradient exists to blend a photograph into the copy beneath it, and
        on the sign it just dimmed the bottom third — the address strip was
        reading as if it were disappearing. z-index:1 lifts only this slide
        over it; the photographs keep their fade. .hero__media is its own
        stacking context on a phone (base sets z-index:0), so this cannot
        leak anywhere else. The slide's own ground then ends on var(--ink) so
        there is no seam where the box meets the copy. */
  /* The box is sized to its contents, not to a ratio: 12px, the stamp's
     (see the block below on where the stamp went),
     the sign at 88vw (940:612, so 57.3vw tall), 12px. Any ratio was an
     approximation that left dead ink under the sign on a wider phone; this
     hugs it on every width. The photographs simply fill whatever the box is. */
  /* No stamp lane at all any more. The owner scribbled over the empty ink
     that sat beside the stamp above the sign and asked for it gone, so the
     sign goes straight under the nav (12px, 57.3vw of sign, 12px) and the
     stamp moves DOWN to the right of the chips row beneath the box, where the
     chips leave ~130px free on the right. It still overlaps nothing: the
     chips are left-aligned and the headline's second line ends before it. */
  .hero__media{aspect-ratio:auto;height:calc(24px + 57.3vw);max-height:none}
  /* 58px under the box puts the circle's top arc past the end of the first
     chip ("OFFICIAL NYS INSPECTION STATION", right edge ~299px at 390) and
     its body beside the second chip and the headline, whose longest line
     ends around x=214. Geometry checked in the browser, not eyeballed. */
  .stamp{width:112px;right:12px;top:calc(24px + 57.3vw + 58px)}
  .hero__slide--art{
    z-index:1;
    /* No slow zoom on this slide. The photographs drift 3-9% across their
       hold, which reads as a pan; a flat sign that grows reads as a mistake,
       and at peak zoom its bottom edge crossed the box and got clipped. An
       !important declaration outranks an animated value, so this switches
       off the transform half of the crossfade and leaves the opacity half. */
    transform:none!important;
    background:
      radial-gradient(76% 108% at 74% 34%,rgba(233,196,74,.20) 0%,rgba(233,196,74,0) 62%),
      linear-gradient(180deg,#150E29 0%,var(--ink) 60%,var(--ink) 100%);
  }
  .hero__slide--art img{
    filter:none;
    /* Anchored to the TOP of its lane — directly under the stamp — not to
       the bottom of the box. The owner's screenshot had it sitting low with
       ink above it; up here it reads as one composition with the stamp. */
    top:12px;bottom:auto;
    left:50%;transform:translateX(-50%);
    width:88vw;
  }
}

/* Inspection guide, closing panel. Already a dark band, so the frame is a
   hairline rather than a slab, and the caption is the muted one. */
.gposter{
  margin:0 0 var(--s5);
  max-width:360px;
  border-radius:var(--r);
  overflow:hidden;
  border:1px solid rgba(233,196,74,.45);
}
.gposter img{display:block;width:100%;height:auto}
.gposter figcaption{
  padding:10px 14px;
  font-family:var(--mono);font-size:.625rem;font-weight:600;
  letter-spacing:.11em;text-transform:uppercase;line-height:1.5;
  color:var(--muted-dark);
  border-top:1px solid rgba(233,196,74,.22);
}
@media (min-width:900px){
  /* Beside the call-to-action rather than above it: the panel is already a
     two-column grid, and a third stacked block pushed the buttons below the
     fold on a laptop.

     Scoped with :has() so the two-column rule only exists while the poster
     does — take the poster out of the v3 strings and the panel goes back to
     its own single-column layout instead of squeezing itself into 360px. A
     browser without :has() simply stacks them, which is the mobile layout. */
  .gcta .wrap:has(.gposter){display:grid;grid-template-columns:360px minmax(0,1fr);gap:var(--s6);align-items:center}
  .gposter{margin-bottom:0}
}

/* --- Phone density ---------------------------------------------------------
   The owner's note, verbatim: "the site takes up too much space, make the
   sizing smaller so more can fit on mobile". Measured before this block at
   390px: 14,610px tall, services alone 3,485px (twelve cards one per row),
   h1 52px over three lines, section titles 40px.

   Everything here is phones only (max-width:719px, the breakpoint the rest of
   the file already uses) and lives in the v3 delta so v1 and v2 render
   exactly as they always did. The desktop scale is untouched — it was sized
   for a laptop and reads well there; it is the phone that was inheriting
   laptop proportions. Nothing structural changes: same sections, same order,
   same words, same buttons. Only size and spacing. --- */
@media (max-width:719px){
  /* Type scale: about three-quarters of the laptop size. Still League Gothic,
     still uppercase; a headline that needed three lines needs three shorter
     ones. */
  .d1{font-size:clamp(2.5rem,10vw,3.25rem)}
  .d2{font-size:clamp(1.85rem,7.4vw,2.5rem)}
  .d3{font-size:1.25rem}
  .lede{font-size:1rem;line-height:1.5}
  .eyebrow{font-size:.625rem}
  .about p,.faq__a p,.insp__item p,.tow__note,.tow__ask{font-size:.9375rem;line-height:1.55}

  /* Sections: the laptop token was clamp(56px, 9vw, 120px). */
  .band{padding-block:40px}
  .sechead{margin-bottom:var(--s4);gap:var(--s1)}

  /* Buttons and chips: still 44px+ tap targets, just not 64px slabs. */
  .btn{min-height:46px;padding:10px 18px}
  .btn--lg{min-height:52px;padding:12px 20px;font-size:1rem}
  .chip{min-height:30px;padding:5px 10px}
  .hero__in{gap:var(--s3);padding-bottom:var(--s4)}
  .hero__foot{font-size:.625rem;gap:6px 14px}

  /* Trust strip: two across instead of a stack of six. */
  .trust ul{grid-template-columns:1fr 1fr}
  .trust li{min-height:48px;padding:12px 14px;font-size:.625rem;letter-spacing:.08em}

  /* Services: the big one. Two columns of compact cards, icon plate two
     thirds the size, body copy a notch smaller. Twelve cards go from twelve
     rows to six. */
  .svc{grid-template-columns:1fr 1fr;gap:10px}
  .svc__card{padding:14px 12px 16px;gap:8px}
  .svc__plate{width:44px;height:44px}
  .svc__icon{width:30px;height:30px}
  .svc__card h3{font-size:1.0625rem;line-height:1.05}
  .svc__card p{font-size:.8125rem;line-height:1.45}

  /* Inspection, tires, towing, shop, visit: the same grids, tighter gaps. */
  .insp{gap:var(--s4)}
  .insp__list{gap:var(--s2);margin-top:var(--s3)}
  .split,.tow__grid,.visit{gap:var(--s4)}
  .tow__truck{width:74%;margin-inline:auto;display:block}
  .recycle{margin-top:var(--s4);padding:var(--s2);gap:var(--s2)}
  .about{margin-top:var(--s4)}
  .gal figcaption{padding:10px 12px}
  .awning{margin-bottom:var(--s3)}
  .sketch{max-width:320px;margin-inline:auto}
  .nap__addr .street{font-size:1.9rem}

  /* FAQ rows and the footer. */
  .faq summary{padding:14px 0;font-size:1.125rem}
  .faq__a{padding-bottom:14px}
  .site-foot{padding-block:var(--s5) var(--s4)}
  .foot__grid{gap:var(--s4)}
}
