/* ==========================================================================
   Home page composition
   ========================================================================== */

/* --------------------------------------------------------------------------
   Masthead — the hero panel and credentials bar are two halves of a single
   rounded card: the hero rounds the top corners, the credentials bar rounds
   the bottom ones, and they meet with no gap. Keeping them in one wrapper is
   what makes the portrait sit flush against the blue band.
   ----------------------------------------------------------------------- */

.masthead {
  margin-bottom: var(--section-gap);
}

/* --- Hero ---------------------------------------------------------------- */

.hero {
  background-color: var(--surface-tint);
  border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  padding: 35px 20px 0;
}

/* No top gap on phones: the masthead bleeds full width there, so any margin
   above it shows as a strip of white page between the header and the hero
   panel — a seam, not breathing room. The gap used to be there to keep the
   header's 0 8px 24px shadow off the headline; the header now draws a 1px
   edge instead (see .site-header in components.css), so there is nothing left
   to get out of the way of. Desktop still insets the card — see below. */

.hero__inner {
  display: grid;
  grid-template-columns: 1fr;
  align-items: end;
}

.hero__content {
  text-align: center;
  padding-bottom: 1rem;
}

.hero__title {
  font-size: var(--h-hero);
  font-weight: 800;
  line-height: 1.1;
  color: var(--color-4);
  margin-bottom: 20px;
}

/* The accent phrase. Flat brand blue is the floor: everything below is an
   enhancement layered on top of it, so a browser that cannot paint gradient
   text still gets the headline as designed. */
.hero__title mark {
  background: none;
  color: var(--primary);
}

/* The accent runs from the brand blue into mint — the same mint as the halo
   behind the portrait, which sits directly beside this line, so the headline
   and the artwork share a colour rather than each having their own.

   It holds pure blue through the first quarter of the phrase: ramping from
   the first letter would read as two-tone text, whereas a late turn reads as
   light falling across one word. The angle is a few degrees off horizontal
   so the turn does not line up with the baseline. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero__title mark {
    /* Named so the rotating accent can paint the identical ramp on itself —
       see .rotator__word, and the note below on why this element must then
       stop painting one. */
    --accent-gradient: linear-gradient(
      96deg,
      var(--primary) 0%,
      var(--primary) 24%,
      var(--accent-mint-deep) 100%
    );
    background-image: var(--accent-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    /* The phrase wraps across two lines at most widths. Cloning gives each
       line its own complete ramp instead of a slice of one box spanning
       both, which is the only version that renders the same everywhere —
       sliced backgrounds on a fragmented inline are where engines differ. */
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
  }

  /* ------------------------------------------------------------------------
     THE ONE THAT BIT: a mark holding the rotator paints no background at all.

     `background-clip: text` clips to the outline of every glyph inside the
     element — and `opacity: 0` on a child does not take that child's glyphs
     out of the mask. It only stops the child painting ITSELF. So while the
     four rotating words sat stacked in one grid cell with three of them at
     opacity 0, this element went on painting its gradient through the union
     of all four outlines at once.

     In Latin that would be a smudge. In Hangul, where a syllable block fills
     its em box, four four-syllable words superimposed are a solid bar — and
     since three of the four end in 치료, those two syllables coincided
     exactly and stayed crisp while the first two turned to mush. That is
     precisely what the headline looked like: 뉴저지 ██치료 전문.

     The words each carry the identical ramp (see .rotator__word), so nothing
     is lost by silencing it here — the visible word paints its own, and a
     hidden one paints nothing.
     --------------------------------------------------------------------- */
  .hero__title mark:has(.rotator) {
    background-image: none;
  }
}

/* Forced-colors drops background images, which would leave transparent text
   painting nothing at all. Hand the phrase back to the system palette. */
@media (forced-colors: active) {
  .hero__title mark {
    background-image: none;
    color: var(--primary);
    -webkit-text-fill-color: currentColor;
  }
}

/* --------------------------------------------------------------------------
   Rotating accent — the headline's one animated element
   Shows one service at a time while all of them stay in the HTML, so the
   headline can be short without the page losing a search term. CSS rather
   than JavaScript: it runs before hydration, survives JS being off, and the
   crawler sees finished markup either way.

   It only ever runs on the Korean home page — the English headline has no
   {rotate} slot — which is why the <mark> interaction documented above went
   unnoticed until somebody looked at /kr/.
   ----------------------------------------------------------------------- */

.rotator {
  /* inline-grid with every word in the same cell stacks them without taking
     them out of flow, so the slot is as wide as the LONGEST word and the
     line never reflows mid-cycle. Absolute positioning would collapse the
     slot to zero and shift the rest of the headline. */
  display: inline-grid;
  vertical-align: top;
}

.rotator__word {
  grid-area: 1 / 1;
  opacity: 0;
  /* Paints the accent ramp on itself rather than inheriting the <mark>'s,
     which is what lets the mark stop painting one — see the note up there.
     Without this the rotating word would render as a blank gap. */
  background-image: var(--accent-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  /* Four words, five seconds each. Long enough that a word is read rather
     than glimpsed, and that the headline is not the busiest thing on a page
     someone landed on in pain. The slide is a sixth of an em — movement
     rather than a blink, and nowhere near a carousel. */
  animation: rotator-swap 20s linear infinite;
}

.rotator__word:nth-child(2) {
  animation-delay: 5s;
}

.rotator__word:nth-child(3) {
  animation-delay: 10s;
}

.rotator__word:nth-child(4) {
  animation-delay: 15s;
}

/* The hold runs to 25% and the fade-out to 28.5%, while the next word starts
   its own cycle at exactly 25% — so the two overlap for 3.5% of the loop and
   cross-fade. Ending the hold before the handover instead leaves a beat with
   no word visible and the headline blinks empty.

   3.5% of 20s is a 0.7s cross-fade. The easing stays linear on purpose: two
   linear ramps in opposite directions sum to a constant, so the pair never
   dips or peaks during the handover. An eased pair would visibly dim at the
   midpoint. */
@keyframes rotator-swap {
  0% {
    opacity: 0;
    transform: translateY(0.18em);
  }
  3.5%,
  25% {
    opacity: 1;
    transform: translateY(0);
  }
  28.5%,
  100% {
    opacity: 0;
    transform: translateY(-0.18em);
  }
}

/* Motion in a headline is the least essential animation on the page. With
   reduced motion the first service simply stays put — the other three are
   still in the markup for crawlers and for assistive tech. */
@media (prefers-reduced-motion: reduce) {
  .rotator__word {
    animation: none;
  }

  .rotator__word:first-child {
    opacity: 1;
  }
}

.hero__text {
  /* A hero lede is conventionally set above body size, and this one was
     inheriting 1.125rem. Dropping it to 1rem sharpens the step down from the
     h1 (a ~2x ratio rather than 1.8x) without going under 16px, which is the
     floor for comfortable body reading on a phone. */
  font-size: 1rem;
  line-height: 1.6;
  margin-bottom: 1.5rem;
}

@media only screen and (min-width: 62.5em) {
  .hero__text {
    font-size: 1.0625rem;
  }
}

/* "Learn more" as an inline link rather than a second button. */
.hero__inline-link {
  display: inline-block;
  font-weight: 700;
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}

.hero__inline-link:hover {
  color: var(--primary-hover);
}

/* The call button with the address and hours alongside it. Shown only where
   the sticky action bar is not. */
.hero__actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-top: 0.5rem;
}

/* The button keeps its width; the address takes whatever is left. */
.hero__actions .hero__cta {
  flex-shrink: 0;
}

.hero__location {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0;
  text-align: left;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--color-3);
}

/* The portrait is bottom-aligned so its baseline meets the credentials bar. */
.hero__media {
  display: flex;
  justify-content: center;
  align-items: flex-end;
}

.hero__media img,
.hero__media picture {
  width: 100%;
  max-width: 420px;
  display: block;
  /* Cancels the inline-image baseline gap that would otherwise leave a
     sliver of hero background below the portrait. */
  vertical-align: bottom;
}

@media only screen and (min-width: 43.125em) {
  .hero {
    padding: 60px 50px 0;
  }
}

@media only screen and (min-width: 62.5em) {
  /* On desktop the masthead is a floating card, so it needs air above it.
     main's padding-top only clears the fixed header — flush against it the
     rounded top corners have nothing to be rounded away from. Mobile keeps
     the flush edge: there the card bleeds full-width and squares off, and
     any gap there would just show a strip of page background. */
  .masthead {
    margin-top: 1.75rem;
  }

  .hero {
    /* Was 80px. Once the card is no longer jammed under the header, that
       much internal padding on top of the new outside gap pushes the
       headline down the fold for nothing. */
    padding: 56px 80px 0;
  }

  .hero__inner {
    grid-template-columns: 1fr 1fr;
    gap: 2.5rem;
  }

  .hero__content {
    text-align: left;

    /* The row is align-items:end so the portrait stands on the credentials
       bar. The copy must not inherit that. This column's height locks once
       the headline stops rewrapping, while the portrait keeps growing with
       the viewport at roughly 0.5px per px of width — so past a hero width of
       about 1060 the portrait is the taller of the two, and bottom-aligning
       dumped the whole difference above the h1: 113px at the 1290 cap, none
       below the crossover. That is what read as zoom-dependent.

       Top-aligned, not centred. Centring splits the slack evenly, which is
       wrong here — the wanted shape is a small fixed gap over the headline
       and the remainder below it. Aligning to the start makes the top gap
       exactly padding-top at every width, and every pixel the portrait gains
       as the viewport widens falls to the bottom instead. */
    align-self: start;

    /* Asymmetric, and both halves are doing a job.

       padding-top IS the gap above the headline — it is the whole top number,
       fixed at 48px from 900px of hero width to the cap.

       padding-bottom is a floor, not a spacer. Below about 1060px of hero
       width this column is the taller of the two and sets the panel height,
       and with no bottom padding the call-to-action row sits flush on the
       credentials bar at 900–960. Above the crossover it is joined by the
       leftover slack, so the bottom grows to roughly 145px at full width. */
    padding-top: 3rem;
    padding-bottom: 2.5rem;
  }

  /* Deliberately uncapped: the portrait fills its column. Capping it was
     tried and reverted — the source is square (850x851), so capping the width
     caps the height too, which shrinks the total slack in the row and takes
     space off the BOTTOM as well as the top. The bottom space is wanted. */
  .hero__media img,
  .hero__media picture {
    max-width: 100%;
  }

}

/* --- Credentials bar ----------------------------------------------------- */

.credentials {
  background-color: var(--primary);
  border-radius: 0 0 var(--radius-panel) var(--radius-panel);
  padding: 20px 10px 30px;
}

.credentials__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 30px 24px;
  list-style: none;
}

.credentials__item {
  flex: 0 0 calc(33.333% - 16px);
  display: flex;
  justify-content: center;
}

.credentials__item img {
  height: 56px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

@media only screen and (min-width: 43.125em) {
  .credentials {
    padding: 50px 30px;
  }

  .credentials__list {
    gap: 50px 32px;
  }

  .credentials__item {
    flex: 0 0 calc(16.666% - 27px);
  }

  .credentials__item img {
    height: 72px;
  }
}

@media only screen and (min-width: 62.5em) {
  .credentials {
    padding: 35px 30px;
  }
}

/* --------------------------------------------------------------------------
   Reviews — headline block beside an aggregate rating
   ----------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Small-screen masthead
   ----------------------------------------------------------------------- */

/* Squared corners belong to the full-bleed treatment, not to the breakpoint
   where the sticky bar appears — above phone width the masthead is an inset
   card again and needs its rounding back. */
@media only screen and (max-width: 43.0625em) {
  .masthead.bleed-mobile .hero,
  .masthead.bleed-mobile .credentials {
    border-radius: 0;
  }
}

@media only screen and (max-width: 62.4375em) {
  /* The sticky call bar carries the phone number on mobile, so the hero
     does not need to spend a 62px button on it. */
  .hero__actions {
    display: none;
  }



  .hero {
    padding: 32px 5vw 0;
  }

  .hero__content {
    padding-bottom: 0.5rem;
  }

  /* The portrait is the largest single block above the fold. Cap it by
     viewport height so the credentials bar stays reachable on short screens
     and does not depend on the phone's aspect ratio. */
  .hero__media img,
  .hero__media picture {
    max-width: min(100%, 62vh);
  }

  .credentials {
    padding: 18px 5vw 22px;
  }

  .credentials__list {
    gap: 18px 14px;
  }

  .credentials__item img {
    height: 44px;
  }
}

