/* =========================================================
   STUDIO NOVO — Home page
   Shared tokens, reset, buttons, header, footer, and the
   scroll-reveal helper now live in common.css (loaded first).
   Only home-page-specific styles remain below.
   ========================================================= */

/* =========================================================
   Hero
   ========================================================= */
.hero{
  min-height: calc(100vh - 78px); /* subtract the sticky header's height (see .header__inner) so header + hero together fill exactly one screen */
  display:flex;
  align-items:center;
  padding-top: 80px; padding-bottom: 80px; overflow:hidden;
}
.hero__inner{
  position: relative;
  width:100%;
  display:grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items:stretch;
}

/* Hero entrance — plays once, on page load, regardless of scroll
   position. Deliberately NOT the [data-reveal] scroll system (common.css):
   the hero is already in view on load, so relying on the scroll
   IntersectionObserver there is a race — it can fire before the browser
   has painted the "hidden" starting state, skipping the animation
   entirely. A plain @keyframes animation always runs top-to-bottom on
   load, so it's used here instead; text leads, the image follows just
   behind it. Respects the site-wide prefers-reduced-motion rule in
   common.css (`* { animation-duration: .001ms !important; }`). */
@keyframes hero-rise{
  from{ opacity:0; transform: translateY(36px); }
  to{ opacity:1; transform: translateY(0); }
}
.hero__text{ animation: hero-rise .9s var(--ease) both; }
.hero__visual{ animation: hero-rise .9s var(--ease) .15s both; }
.hero__title{
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  line-height: 1.12;
}
.hero__title em{ font-style:italic; font-weight:600; }
.hero__desc{
  margin-top: 22px; max-width: 440px; color: var(--ink-soft); font-size: 1.05rem;
}
.hero__checks{ margin-top: 22px; display:flex; flex-direction:column; gap:4px; }
.hero__checks li{ font-size:.95rem; color: var(--ink-soft); padding-left:24px; position:relative; }
.hero__checks li::before{
  content:"✓"; position:absolute; left:0; color: var(--green); font-weight:600;
}
.hero__desc + .hero__checks{ margin-bottom: 34px; }
.hero .btn{ margin-top: 34px; }

/* hero visual — desktop: stretch to match the height of the text
   column next to it (grid row default), so the image fills the
   available space instead of being capped to a fixed crop. */
.hero__visual{ position:relative; height:100%; }
.hero__visual-img{
  display:block; width:100%; height:100%; object-fit:cover; object-position: center;
}

/* placeholder blocks */
.ph{
  width:100%; height:100%;
  display:flex; flex-direction:column; justify-content:flex-end; position:relative;
}
.ph__tag{ position:absolute; top:16px; left:18px; font-size:.68rem; letter-spacing:.14em; font-weight:600; }
.ph__label{ font-family: var(--serif); font-size:1rem; line-height:1.3; }
.ph--dark{ background: linear-gradient(160deg,#22281f,#0f120d); color:#EDE9DC; }
.ph--sage{ background: linear-gradient(160deg,#d9d2bf,#bcb49c); color:#2b2a22; }
.ph--coffee{ background: linear-gradient(160deg,#4b3a2a,#221812); color:#EFE7D8; }
.ph--stone{ background: linear-gradient(160deg,#dedad0,#c7c2b3); color:#33322a; }
.ph--cream{ background: linear-gradient(160deg,#eee9db,#d8d2bf); }
.ph--wood{ background: linear-gradient(160deg,#8a6b4a,#4f3c28); }
.ph--paper{ background: linear-gradient(160deg,#f2efe4,#dcd7c6); }
.ph--dusk{ background: linear-gradient(160deg,#c9b7a6,#8f7461); }

/* =========================================================
   Process
   ========================================================= */
.process__grid{
  display:grid; grid-template-columns: repeat(3,1fr);
}
.process__step{
  padding: 4px 40px;
  border-left: 1px solid var(--line);
}
.process__step:first-child{ border-left:none; padding-left:0; }
/* Was sized for inline SVG icons (width/height + currentColor fill).
   The markup now uses <img> PNG icons instead, which come in at
   inconsistent native sizes and ignore `color` — pin a fixed box,
   object-fit:contain so nothing stretches or crops, and display:block
   so the img's own inline-baseline spacing doesn't add extra gap
   above .process__num. */
.process__icon{
  width:44px; height:44px;
  object-fit: contain;
  display:block;
  margin-bottom: 26px;
}
.process__num{
  display:block; font-family: var(--serif); font-size:1.6rem;  margin-bottom: 10px;
}
.process__step h3{ font-size:1.15rem; margin-bottom:10px; font-weight: bolder;}
.process__step h3 small{ display:block; font-family: var(--sans); font-weight:400; font-size:.8rem; color: var(--ink-faint); margin-top:3px; }
.process__step p{ color: var(--ink-soft); font-size: .93rem; }

/* =========================================================
   Templates (home preview)
   — .tabs/.tab and .pill base rules now live in common.css
     (shared with templates.html); only the deltas stay here.
   ========================================================= */
.tabs{ margin-bottom: 48px; }

.cards{ display:grid; grid-template-columns: repeat(3,1fr); gap: 26px; }
.card.is-hidden{ display:none; }
/* contain:paint reinforces overflow:hidden's clipping for the animated
   (mobile crossfade) images inside — on some mobile browsers, a CSS
   `animation` on an absolutely-positioned child can get promoted to its
   own compositing layer and paint outside an ancestor's overflow:hidden
   bounds; contain:paint forces the browser to clip strictly to this
   box regardless. */
.card{
  background: var(--paper); border:1px solid var(--line); border-radius: var(--radius-lg);
  overflow:hidden; contain: paint; display:flex; flex-direction:column;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease);
}
.card:hover{ transform: translateY(-6px); box-shadow: 0 24px 40px -20px rgba(20,40,29,.2); }
/* min-width:0 overrides the flex item default (min-width:auto), which
   otherwise lets this box's content (the images inside) push it wider
   than the card — the classic cause of an image bleeding past its
   container's edges in a column flex layout. width:100% makes it size
   from its own container explicitly rather than relying on flex-stretch
   alone. contain:paint is the same clipping reinforcement as .card above. */
.card__img{
  width: 100%;
  min-width: 0;
  contain: paint;
  height: 190px;
  overflow: hidden;
  position: relative;
}
.card__img img{
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}
/* Cards with a hover-preview image (see templates.html for the same
   pattern) — higher specificity than ".card__img img" above so the
   absolute positioning/opacity actually take effect. */
.card__img .card__img-default,
.card__img .card__img-hover{
  position: absolute; inset: 0;
  transition: opacity .35s var(--ease);
}
.card__img .card__img-hover{ opacity: 0; object-position: top; }
.card:hover .card__img .card__img-default{ opacity: 0; }
.card:hover .card__img .card__img-hover{ opacity: 1; }
.card__body{ padding: 22px 22px 26px; display:flex; flex-direction:column; gap:12px; flex:1; }
.card__top{ display:flex; align-items:center; justify-content:space-between; }
.card__top h3{ font-size:1.05rem; }
.card__body p{ color: var(--ink-soft); font-size:.88rem; flex:1; }
.link{ font-size:.88rem; font-weight:500; color: var(--green); }
.link .arrow{ transition: transform .3s var(--ease); display:inline-block; }
.link:hover .arrow{ transform: translateX(4px); }

/* =========================================================
   Pricing (home preview)
   ========================================================= */
.plans{ display:grid; grid-template-columns: repeat(3,1fr); gap: 26px; align-items:stretch; }
.plan{
  background: var(--paper); border:1px solid var(--line); border-radius: var(--radius-lg);
  padding: 34px 30px; display:flex; flex-direction:column;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease);
}
.plan:hover{ transform: translateY(-6px); box-shadow: 0 24px 40px -20px rgba(20,40,29,.18); }
.plan--featured{
  position: relative;
  border: 1px solid var(--green);
  border-radius: 20px;
  transform: scale(1.03);
}
.plan--featured:hover{
  transform: scale(1.03) translateY(-6px);
}
.plan__badge{
  position: absolute;
  top: -22px;
  background: var(--green);
  color: white;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  border: none;
}
.plan h3{ font-size:1.2rem; margin-bottom:10px; }
.plan__desc{ color: var(--ink-soft); font-size:.9rem; min-height: 42px; }
.plan__price{ font-family: var(--serif); font-size:2.4rem; margin: 22px 0 20px; }
.plan__list{ display:flex; flex-direction:column; gap:10px; margin-bottom: 30px; }
.plan__list li{ font-size:.9rem; color: var(--ink-soft); padding-left:24px; position:relative; }
.plan__list li::before{ content:"✓"; position:absolute; left:0; color: var(--green); font-weight:600; }
.plan .btn{ align-self:flex-start; width:100%; justify-content:center; margin-top: 30px;}

/* Signature plan — "See all features" toggle (see price.css for the
   full rationale); mirrors the same checkbox-hack pattern here so the
   home page preview card matches the pricing page. */
.plan__more-check{
  width:1px; height:1px; margin:-1px; padding:0; border:0;
  clip-path: inset(50%); overflow:hidden; white-space:nowrap;
}
.plan__list-extra{ display:none; }
.plan__more-check:checked ~ .plan__list .plan__list-extra{ display:block; }
.plan__more-toggle{
  display:inline-flex; cursor:pointer;
  font-size:.85rem; font-weight:500; color: var(--green); margin-bottom: 16px;
}
.plan__more-toggle:hover{ color: var(--green-dark); }
.plan__more-toggle-text-less{ display:none; }
.plan__more-check:checked ~ .plan__more-toggle .plan__more-toggle-text-more{ display:none; }
.plan__more-check:checked ~ .plan__more-toggle .plan__more-toggle-text-less{ display:inline; }

/* Starter/Business have no "See all features" toggle, so their notes
   sat higher than Signature's — an invisible same-size stand-in
   (same classes, just hidden) reserves that exact height so the
   border above every card's note lines up across the row. */
.plan__more-toggle--spacer{ visibility:hidden; pointer-events:none; }

/* Signature plan — small upsell note (Need an online shop?), same idea
   as price.html's plan__best blocks; home page cards don't use that
   component, so a lighter-weight version lives here instead. */
.plan__note{
  border-top: 1px solid var(--line); padding-top: 14px; margin-bottom: 20px;
  font-size: .82rem; color: var(--ink-soft);
}
.plan__note strong{ display:block; color: var(--ink); margin-bottom: 2px; }
.plan--featured .btn--primary{
  width: 100%;
  background: var(--green);
  color: white;
  border-radius: 999px;
  padding: 14px 26px;
  font-size: 1rem;
  font-weight: 600;
}
.plan--featured .btn--primary:hover{
  background: var(--green-dark);
}

/* =========================================================
   Our Work — ticker
   ========================================================= */
/* The ticker is the last thing inside .work, so its own margin-bottom
   stacks with .work's section padding-bottom and Testimonials' own
   padding-top to form the visible gap between the two sections. .work
   carries no bottom padding of its own, and the ticker's margin-bottom
   plus Testimonials' own padding-top are both deliberately tightened
   well below the generic `section` padding so this gap reads
   noticeably closer than a standard section-to-section gap — see the
   Tablet/Mobile responsive blocks for their values. */
.work{ padding-bottom: 0; }
.work .section-head{ margin-bottom: 48px; }
.ticker{
  width:100%; overflow:hidden;
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  margin-bottom: 56px;
}
.testimonials{ padding-top: 56px; }
.ticker__track{
  display:flex;
  width: max-content;
  gap: 26px;
  animation: ticker-scroll 32s linear infinite;
}
.ticker:hover .ticker__track{ animation-play-state: paused; }
@keyframes ticker-scroll{
  from{ transform: translateX(0); }
  to{ transform: translateX(-50%); }
}
.ticker__item{ width: 320px; flex: 0 0 auto; }
.work__img{ height: auto; border-radius: var(--radius-lg); margin-bottom: 16px; }
.ticker__item h4{ font-size:1rem; margin-bottom: 2px; }
.ticker__item p{ font-size:.85rem; color: var(--ink-faint); }

/* =========================================================
   Testimonials
   ========================================================= */
.quotes{ display:grid; grid-template-columns: repeat(3,1fr); gap: 26px; }
.quote{
  background: var(--paper); border:1px solid var(--line); border-radius: var(--radius-lg);
  padding: 30px 28px;
}
.quote__mark{ font-family: var(--serif); font-size:2.6rem; color: var(--green); line-height:1; display:block; margin-bottom:8px; }
.quote p{ color: var(--ink-soft); font-size:.92rem; margin-bottom: 22px; }
.quote__name{ font-weight:600; font-size:.92rem; }
.quote__company{ font-size:.82rem; color: var(--ink-faint); }

/* =========================================================
   Section base spacing (home only — other pages set their own)
   ========================================================= */
section{ padding: 72px 0; } /* was 100px — narrowed per feedback */

/* =========================================================
   Responsive — Tablet
   ========================================================= */
@media (max-width: 1024px){
  section{ padding: 64px 0; } /* was 96px — narrowed per feedback */
  /* Tightened Work→Testimonials gap at this breakpoint — see the
     "Our Work — ticker" comment above. */
  .ticker{ margin-bottom: 46px; }
  .testimonials{ padding-top: 46px; }
  /* min-height:100vh (set for desktop so header+hero fill exactly one
     screen) forces the hero to full viewport height even after the
     image+text stack into a single column below and take up far less
     room — that mismatch was showing up as a huge empty gap before the
     Process section. Let the hero size to its own content instead. */
  .hero{ min-height: auto; padding-top: 60px; padding-bottom: 60px; }
  .hero__inner{ grid-template-columns: 1fr; gap: 40px; }
  /* Full natural height (previous fix) showed the whole photo but made
     the box quite tall. A moderate aspect-ratio trims a bit off the top
     and bottom (background/surroundings) while keeping the centred
     laptop + phone fully in frame, instead of the old fixed 340px box
     which cropped too aggressively. Nudged from 4/3 to 7/5 per feedback
     to trim a little more. */
  .hero__visual{ order:-1; height: auto; aspect-ratio: 7 / 5; }
  .hero__visual-img{ height: 100%; object-position: center; }
  .cards{ grid-template-columns: repeat(2,1fr); }
  .plans{
    grid-template-columns: 1fr;
    max-width: 520px;
    margin: 0 auto;
  }
  .plan--featured{
    grid-column: auto;
    order: 0;
    transform: none;
  }
  .plan--featured:hover{
    transform: translateY(-6px);
  }
  .quotes{ grid-template-columns: repeat(2,1fr); }
  .quotes .quote:last-child{ grid-column: span 2; }
}

@media (max-width: 768px){
  .process__grid{ grid-template-columns:1fr; gap: 40px; }
  .process__step{ border-left:none; padding:0; padding-left: 0; border-top:1px solid var(--line); padding-top: 30px; }
  .process__step:first-child{ border-top:none; padding-top:0; }
}

/* =========================================================
   Responsive — Mobile
   ========================================================= */
@media (max-width: 680px){
  /* Was 72px — combined with the previous section's own 72px bottom
     padding that put ~144px of blank space between sections on mobile,
     reading as "too much space above" each one. Tightened overall. */
  section{ padding: 48px 0; }
  .section-head{ margin-bottom: 32px; }

  /* .hero keeps the tablet breakpoint's 60px padding-top (higher
     specificity than the `section` rule above) unless overridden here —
     that's the gap that was showing above the hero image on mobile, since
     .hero__visual is reordered to the top of the stack at this width.
     Tighten mobile only; tablet (681–1024px) is untouched. */
  .hero{ padding-top: 0; }

  .hero__title{ font-size: 2.2rem; }
  /* Slightly more cropped than the tablet breakpoint (3/2 vs 4/3) per
     feedback that desktop + mobile needed a bit more trimmed off the
     top/bottom, while keeping the centred laptop + phone in frame. */
  .hero__visual{ height: auto; aspect-ratio: 3 / 2; }
  .hero__visual-img{ height: 100%; object-position: center; }
  .hero__desc{ max-width:none; }

  .cards{ grid-template-columns: 1fr; }
  /* There's no hover on touch, so a card with a second (hover) image
     cross-fades between the two automatically instead — same
     absolute-positioned layering as desktop, just driven by a looping
     animation rather than :hover. Cards with only a default image
     (:not(:has(.card__img-hover))) keep the old static, natural-height
     treatment, since there's nothing to cross-fade with.
     16/9 (not 4/3) — these photos are wide homepage screenshots
     (~16:9-ish). object-fit:cover on a box NARROWER than the source
     (4/3 is much narrower than ~16/9) crops from the left/right, which
     was cutting off the nav bar and logo text on the sides. Desktop's
     fixed 190px-tall box is wide enough that it crops top/bottom
     instead (never an issue) — 16/9 gives mobile the same safe crop
     direction. */
  .card__img:has(.card__img-hover){ width:100%; max-width:100%; height: auto; aspect-ratio: 16 / 9; }
  .card__img:has(.card__img-hover) .card__img-default,
  .card__img:has(.card__img-hover) .card__img-hover{
    width:100%; height:100%; object-fit:cover;
  }
  .card__img:has(.card__img-hover) .card__img-default{ animation: card-crossfade-default 9s ease-in-out infinite; }
  .card__img:has(.card__img-hover) .card__img-hover{ opacity:0; object-position: top; animation: card-crossfade-hover 9s ease-in-out infinite; }
  /* Stagger every other card half a cycle so the whole grid doesn't
     flip in lockstep. */
  .card:nth-child(even) .card__img-default,
  .card:nth-child(even) .card__img-hover{ animation-delay: -4.5s; }

  .card__img:not(:has(.card__img-hover)){ height: auto; }
  .card__img:not(:has(.card__img-hover)) .card__img-default{ position: static; width: 100%; height: auto; }

  .plans{ grid-template-columns: 1fr; }
  .plan--featured{ grid-column: span 1; order:-1; }
  .quotes{ grid-template-columns: 1fr; }
  .quotes .quote:last-child{ grid-column: span 1; }

  /* Tighten the gap between the "Launch in 3-7 days" checklist item and
     the View Templates CTA button below it — the base 34px margin-top
     (set for desktop under .hero .btn) reads as too much breathing room
     once everything is stacked in a single mobile column. Narrowed
     further per feedback (was 18px). */
  .hero .btn{ margin-top: 8px; }

  /* Icons were sized (44px) for the 3-column desktop/tablet grid — scale
     down for mobile and reuse them as the marker on the timeline line
     below instead of stacking them above the number. */
  .process__icon{ width: 32px; height: 32px; margin-bottom: 0; }

  /* Timeline layout (mobile only), matching the reference: icon sits in
     a fixed-width left column acting as a line marker; number, heading
     and paragraph are indented into the right column so they all line
     up with each other instead of spanning full width under the icon.
     The base (non-media-query) rule `.process__step:first-child{
     border-left:none; padding-left:0 }` is more specific than a plain
     `.process__step{...}` here, so it's re-declared on :first-child too
     — otherwise step 01 alone drifts out of alignment with 02/03. */
  .process__step{
    position: relative;
    display: grid;
    grid-template-columns: 32px 1fr;
    column-gap: 20px;
    row-gap: 8px;
    align-items: start;
    border-left: none;
    border-top: none;
    padding: 0 16px;
  }
  .process__step:first-child{ border-top: none; padding: 0 16px; }
  /* background:var(--cream) — the icon PNGs are transparent between their
     linework, so the timeline rule behind them (z-index:0, below) was
     showing through those gaps instead of being hidden by the icon.
     Matching the page background over the icon's own box blocks the
     line wherever it passes underneath, without needing to touch the
     line's own geometry. */
  .process__icon{ grid-column: 1; grid-row: 1; align-self: center; position: relative; z-index: 1; background: var(--cream); }
  .process__num{ grid-column: 2; grid-row: 1; align-self: center; margin-bottom: 0; }
  .process__step h3{ grid-column: 2; grid-row: 2; }
  .process__step p{ grid-column: 2; grid-row: 3; }

  /* Continuous vertical line running through the icon markers. Anchored
     to this step's own icon center (top:16px = half the 32px icon) and
     stretched past the step's own bottom edge through the grid's 40px
     row gap to the next icon's center (40px + 16px = 56px), so the line
     reads as one continuous rule regardless of how tall each step's
     text is. The last step has no next icon to reach, so its line is
     removed. */
  .process__step::before{
    content: "";
    position: absolute;
    left: 31px;
    top: 16px;
    bottom: -56px;
    width: 1px;
    background: var(--line);
    z-index: 0;
  }
  .process__step:last-child::before{ content: none; }

  .ticker__item{ width: 240px; }
  /* Let the image size itself naturally (matches the base/desktop rule
     above) instead of forcing a fixed height — a fixed height needs
     object-fit:cover to fill it, which crops the sides off since the
     box's ratio doesn't match the photo's. Auto height means the whole
     image is always shown, scaled to the 240px ticker item width. */
  .work__img{ height: auto; }

  /* Tightened Work→Testimonials gap at this breakpoint — see the
     "Our Work — ticker" comment near the top of this file. (.work's own
     padding-bottom is already 0 at every breakpoint.) */
  .ticker{ margin-bottom: 56px; }
  .testimonials{ padding-top: 56px; }
}

@keyframes card-crossfade-default{
  0%, 40%{ opacity:1; }
  50%, 90%{ opacity:0; }
  100%{ opacity:1; }
}
@keyframes card-crossfade-hover{
  0%, 40%{ opacity:0; }
  50%, 90%{ opacity:1; }
  100%{ opacity:0; }
}
@media (prefers-reduced-motion: reduce){
  .card__img-default, .card__img-hover{ animation: none !important; }
}
