/* Shared motion (spec 2026-10-18): one rhythm for the whole site.
   Hidden-before-reveal only applies with .js, so content is always there without JavaScript. */
:root {
  --ease-arrive: cubic-bezier(.22, 1, .36, 1);
  --ease-leave: cubic-bezier(.4, 0, 1, 1);
  --t-enter: .45s;
  --t-exit: .28s;
}

.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .6s var(--ease-arrive), transform .6s var(--ease-arrive);
}

.js .reveal.in {
  opacity: 1;
  transform: none;
}

.reveal-stagger > .reveal:nth-child(2) { transition-delay: .05s; }
.reveal-stagger > .reveal:nth-child(3) { transition-delay: .1s; }
.reveal-stagger > .reveal:nth-child(4) { transition-delay: .15s; }

.button {
  cursor: pointer;
}

.button:active {
  transform: scale(.97);
}

.button:focus-visible,
a:focus-visible {
  outline: 3px solid var(--ocean-700);
  outline-offset: 3px;
}

/* Phosphor duotone icons: brand blue line, soft LINE-green fill */
.ph {
  color: #0b5d9a;
}

.ph path[opacity] {
  fill: #16a34a;
  opacity: .28;
}

@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .reveal.in {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Thai line breaking: key phrases stay on one line; paragraphs avoid a lone last word */
.nw {
  white-space: nowrap;
}

p,
li,
summary,
.lead {
  text-wrap: pretty;
}

/* small phones: smaller headings so phrases fit without being cut mid-word */
@media (max-width: 480px) {
  h1 {
    font-size: 2.15rem;
  }

  h2 {
    font-size: 1.6rem;
  }
}

/* base.css limits headings to 13.5ch/15ch, which suits English but forces Thai headings to break mid-phrase */
h1 {
  max-width: 20em;
}

h2 {
  max-width: 24em;
}

/* grid/flex children may shrink below their longest unbreakable phrase (the phrase then wraps) */
.grid > *,
.ip-grid > *,
.ip-steps > *,
.hm-features__grid > *,
.hm-story__stage > *,
.footer-grid > * {
  min-width: 0;
}

/* Inner-page motion (2026-10-18). Everything here is off for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  /* hero: picture floats gently, text rises line by line on load */
  .ip-hero__art,
  .trial-hero-art {
    animation: art-float 7s ease-in-out infinite alternate;
  }

  .js .ip-hero__copy > *,
  .js .trial-hero > * {
    animation: hero-in .7s var(--ease-arrive) both;
  }

  .js .ip-hero__copy > :nth-child(2), .js .trial-hero > :nth-child(2) { animation-delay: .08s; }
  .js .ip-hero__copy > :nth-child(3), .js .trial-hero > :nth-child(3) { animation-delay: .16s; }
  .js .ip-hero__copy > :nth-child(4), .js .trial-hero > :nth-child(4) { animation-delay: .24s; }
  .js .ip-hero__copy > :nth-child(5), .js .trial-hero > :nth-child(5) { animation-delay: .32s; }

  /* steps: a green bar fills across the cards as you scroll, the reached step's icon lights up */
  .js .ip-steps li {
    position: relative;
    overflow: hidden;
  }

  .js .ip-steps li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 4px;
    height: 100%;
    background: #16a34a;
    transform: scaleY(var(--f, 0));
    transform-origin: top;
  }

  .js .ip-step-icon {
    transition: background .35s ease, transform .35s var(--ease-arrive);
  }

  .js .ip-steps li.on .ip-step-icon {
    background: linear-gradient(135deg, #d6f1e1, #c3ead3);
    transform: scale(1.06);
  }

  /* examples: mini chats play like a real conversation */
  .ip-chat.wait > p {
    position: relative;
    opacity: 0;
    transform: translateY(8px) scale(.96);
    transform-origin: left bottom;
    transition: opacity .35s var(--ease-arrive), transform .35s var(--ease-arrive);
  }

  .ip-chat.wait > .out { transform-origin: right bottom; }
  .ip-chat.wait > .chip { transform-origin: center bottom; }

  .ip-chat.wait > p.show {
    opacity: 1;
    transform: none;
  }

  .ip-chat.wait > p.typing {
    opacity: 1;
    transform: none;
    border-color: transparent;
    background: transparent;
    color: transparent;
  }

  .ip-chat.wait > p.typing::after {
    content: "•••";
    position: absolute;
    top: 0;
    right: 0;
    display: grid;
    width: 58px;
    height: 36px;
    place-items: center;
    border-radius: 18px 18px 6px 18px;
    background: #16a34a;
    color: #fff;
    letter-spacing: 3px;
    animation: typing-pulse 1s ease-in-out infinite;
  }

  .ip-chat.wait > .chip.typing::after {
    right: auto;
    left: 50%;
    border-radius: 99px;
    background: #e8f7ee;
    color: #12723a;
    translate: -50% 0;
  }
}

@media (prefers-reduced-motion: no-preference) and (min-width: 1000px) {
  .js .ip-steps li::before {
    width: 100%;
    height: 4px;
    transform: scaleX(var(--f, 0));
    transform-origin: left;
  }
}

@keyframes art-float {
  from { transform: translateY(-6px); }
  to { transform: translateY(8px); }
}

/* transform only: the hero text is never invisible, even where animations do not run */
@keyframes hero-in {
  from { transform: translateY(14px); }
  to { transform: none; }
}

@keyframes typing-pulse {
  50% { opacity: .55; }
}

/* Motion, part 2 (2026-10-18): icons, about page, compare ticks, trial form */
@media (prefers-reduced-motion: no-preference) {
  /* icons pop in a moment after their card arrives */
  .js .reveal .ip-tile .ph,
  .js .reveal .ip-step-icon .ph {
    transform: scale(.55) rotate(-10deg);
    transition: transform .55s cubic-bezier(.34, 1.56, .64, 1) .18s;
  }

  .js .reveal.in .ip-tile .ph,
  .js .reveal.in .ip-step-icon .ph {
    transform: none;
  }

  /* about: the green line beside the story grows downward */
  .js .ip-story__text {
    position: relative;
    border-left-color: transparent;
  }

  .js .ip-story__text::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -4px;
    width: 4px;
    background: #16a34a;
    transform: scaleY(0);
    transform-origin: top;
    transition: transform 1s var(--ease-arrive) .25s;
  }

  .js .ip-story__text.in::before {
    transform: none;
  }

  /* about: the problem is crossed out, then the assistant's answer slides in */
  .js .ip-strike {
    background: linear-gradient(currentColor, currentColor) left 56% / 0 2px no-repeat;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    transition: background-size .5s ease .55s, color .5s ease .55s;
  }

  .js .reveal.in .ip-strike {
    background-size: 100% 2px;
    color: var(--muted);
  }

  .js .reveal .ip-fix {
    transform: translateX(-14px);
    transition: transform .5s var(--ease-arrive) 1.05s;
  }

  .js .reveal.in .ip-fix {
    transform: none;
  }

  /* about: the arrows between the three steps pulse one after another */
  .ip-flow li:not(:last-child)::after {
    animation: arrow-pulse 2.4s ease-in-out infinite;
  }

  .ip-flow li:nth-child(2)::after {
    animation-delay: .8s;
  }

  /* services: ticks pop in row by row once the table arrives */
  .js .reveal .ip-yes {
    scale: .3;
    transition: scale .45s cubic-bezier(.34, 1.56, .64, 1);
    transition-delay: calc(.25s + var(--i, 0) * .09s);
  }

  .js .reveal.in .ip-yes {
    scale: 1;
  }

  /* trial: a soft green glow on the field being filled, and a check that draws itself after sending */
  .trial-form input,
  .trial-form textarea,
  .trial-form select {
    transition: border-color .2s ease, box-shadow .2s ease;
  }

  .trial-check circle,
  .trial-check path {
    animation: draw .6s var(--ease-arrive) both;
  }

  .trial-check path {
    animation-delay: .35s;
  }
}

.trial-form input:focus,
.trial-form textarea:focus,
.trial-form select:focus {
  border-color: #16a34a;
  box-shadow: 0 0 0 6px rgba(22, 163, 74, .16);
}

.trial-check {
  display: block;
  margin-bottom: 14px;
}

.trial-check circle {
  fill: #e8f7ee;
  stroke: #16a34a;
  stroke-width: 3;
  stroke-dasharray: 176;
}

.trial-check path {
  fill: none;
  stroke: #16a34a;
  stroke-width: 4;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 40;
}

@keyframes draw {
  from { stroke-dashoffset: var(--len, 176); }
  to { stroke-dashoffset: 0; }
}

.trial-check path { --len: 40; }

@keyframes arrow-pulse {
  0%, 40%, 100% { scale: 1; box-shadow: 0 0 0 0 rgba(22, 163, 74, 0); }
  20% { scale: 1.18; box-shadow: 0 0 0 6px rgba(22, 163, 74, .18); }
}
