/* Hello Hudson homepage: global motion and focus rules (not tied to one class). */
a:focus-visible, button:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; border-radius: 6px; }
/* Starts far enough down (130%) to stay hidden below the line's descender space while it waits. */
@keyframes hh-rise { from { transform: translateY(130%); } to { transform: none; } }
/* Entrance fades start at 1% opacity, not 0: browsers skip fully transparent text when measuring Largest Contentful Paint, which left PageSpeed with no LCP at all. Looks identical. */
@keyframes hh-fade { from { opacity: 0.01; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes hh-open { from { clip-path: inset(6% 3% 0 3% round 24px); } to { clip-path: inset(0 0 0 0 round 24px); } }
@keyframes hh-widen { from { clip-path: inset(0 var(--inset) round 24px); } to { clip-path: inset(0 0 round 24px); } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}


/* Inner pages: content sits in a centred column (a step in from the full-width hero, header and footer). */
:root { --measure: 105rem; }


/* Mobile menu logo: fades in (light) once the menu reveal has passed it. */
@keyframes hh-logo-in { from { opacity: 0; } to { opacity: 1; } }


@keyframes hh-pop { from { transform: scale(0.4); opacity: 0; } to { transform: none; opacity: 1; } }


/* Page transitions between pages of the site (same-origin navigations). The header stays put; the old
   page fades and settles back slightly, the new one fades in (and lifts a touch on wider screens). Phones
   get no lift so it doesn't stack with the hero text rising in. Browsers without cross-document view
   transitions just navigate normally. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  /* The header stays put across page changes. Named per part, not on the header itself: a named ancestor stops the menu pill's backdrop blur from seeing the page. */
  .site-header__logo { view-transition-name: hh-logo; }
  .site-header__menu { view-transition-name: hh-nav; }
  .site-header__actions { view-transition-name: hh-actions; }
  /* Header parts glide between pages: from a scrolled page, the logo and Get in touch drop back in and the menu pill shrinks as the HH mark leaves. */
  ::view-transition-group(hh-logo), ::view-transition-group(hh-nav), ::view-transition-group(hh-actions) { animation-duration: 0.5s; animation-timing-function: var(--ease-brand); }
  ::view-transition-old(hh-logo), ::view-transition-new(hh-logo), ::view-transition-old(hh-actions), ::view-transition-new(hh-actions) { animation-duration: 0.4s; }
  /* The pill: both snapshots keep their real size, pinned right (the links line up, the mark is clipped away on the left), inside a rounded clip. */
  ::view-transition-group(hh-nav) { border-radius: 999px; overflow: clip; }
  ::view-transition-old(hh-nav), ::view-transition-new(hh-nav) { inline-size: auto; block-size: 100%; inset-inline: auto 0; animation-duration: 0.5s; }
  ::view-transition-old(root) { animation: hh-vt-out 0.26s cubic-bezier(0.4, 0, 1, 1) both; }
  ::view-transition-new(root) { animation: hh-vt-in 0.42s cubic-bezier(0.2, 0.7, 0.1, 1) 0.1s both; }
}
@media (prefers-reduced-motion: no-preference) and (min-width: 768px) {
  ::view-transition-new(root) { animation-name: hh-vt-in-lift; }
}
@keyframes hh-vt-out { to { opacity: 0; transform: scale(0.985); } }
@keyframes hh-vt-in { from { opacity: 0; } }
@keyframes hh-vt-in-lift { from { opacity: 0; transform: translateY(16px); } }


/* Slide-through arrows. The real glyph keeps its space (but is painted transparent); two copies
   drawn by ::before (resting, leaves on hover) and ::after (waits behind, slides in) do the moving.
   Direction modifiers: btn__arrow--down (↓) and btn__arrow--out (↗, external links). */
.btn__arrow, .q-card__arrow, .service__go > span {
  position: relative;
  display: inline-block;
  clip-path: inset(0 -0.1em);
  -webkit-text-fill-color: transparent;
  --arrow: "→";
  --arrow-out: translateX(115%);
  --arrow-in: translateX(-115%);
}
.btn__arrow--down { --arrow: "↓"; --arrow-out: translateY(110%); --arrow-in: translateY(-110%); clip-path: inset(0 -0.1em); }
.btn__arrow--out { --arrow: "↗"; --arrow-out: translate(115%, -110%); --arrow-in: translate(-115%, 110%); }
.btn__arrow::before, .btn__arrow::after, .q-card__arrow::before, .q-card__arrow::after, .service__go > span::before, .service__go > span::after {
  content: var(--arrow);
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 100%;
  text-align: center;
  -webkit-text-fill-color: currentColor;
  transition: transform 0.42s cubic-bezier(0.65, 0, 0.35, 1);
}
.btn__arrow::after, .q-card__arrow::after, .service__go > span::after { transform: var(--arrow-in); }
:where(a, button):hover .btn__arrow::before, :where(a, button):focus-visible .btn__arrow::before,
:where(a, button):hover .q-card__arrow::before, :where(a, button):focus-visible .q-card__arrow::before,
:where(a, button):hover .service__go > span::before, :where(a, button):focus-visible .service__go > span::before { transform: var(--arrow-out); }
:where(a, button):hover .btn__arrow::after, :where(a, button):focus-visible .btn__arrow::after,
:where(a, button):hover .q-card__arrow::after, :where(a, button):focus-visible .q-card__arrow::after,
:where(a, button):hover .service__go > span::after, :where(a, button):focus-visible .service__go > span::after { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .btn__arrow::after, .q-card__arrow::after, .service__go > span::after { display: none; }
  .btn__arrow::before, .q-card__arrow::before, .service__go > span::before { transform: none !important; transition: none; }
}



/* Hero text waits for the web fonts (up to 1.2s; the class is set by the SiteHeader head script),
   so it doesn't swap fonts and re-wrap halfway through rising in. */
/* ...and, after a page transition, until the transition has finished (vt-wait). */
html:is(.fonts-wait, .vt-wait) :is(.hero-band, .page-band, .legal-band) *,
html:is(.fonts-wait, .vt-wait) :is(.hero-band, .page-band, .legal-band) ~ * { animation-play-state: paused !important; }

/* The first section after the hero fades in once the heading has risen. Opacity only, so it never
   changes how fixed or sticky things inside it behave. */
@media (prefers-reduced-motion: no-preference) {
  :is(.hero-band, .page-band, .legal-band) ~ * { animation: hh-after-hero 0.7s 0.45s ease-out both; }
}
@keyframes hh-after-hero { from { opacity: 0.01; } }


/* Lazy photos fade in over their card's background once loaded (site.js adds the classes; cached photos skip it). */
/* An animation, not a transition: setting transition here would replace the image's own (e.g. the project card hover zoom). */
img.hh-img-fade { opacity: 0; }
img.hh-img-fade.is-loaded { opacity: 1; animation: hh-img-in 0.6s ease-out; }
@keyframes hh-img-in { from { opacity: 0; } }


/* iOS turns numbers, dates and addresses into links with its own colours, which vanish on dark sections.
   The format-detection meta (SiteHeader) stops phone numbers; this keeps anything else it links looking like the text around it. */
a[x-apple-data-detectors] { color: inherit !important; text-decoration: none !important; font: inherit !important; }


/* Business card pages (/ryan/, /cas/): the card rises in. */
@keyframes vc-rise { from { opacity: 0.01; transform: translateY(16px); } to { opacity: 1; transform: none; } }
