1// Hero banner carousel: 2// ⢠Desktop (â¥761px): manual carousel with prev/next arrows. 3// ⢠SP (â¤760px): continuous "conveyor belt" â autoplay (delay:0 + freeMode) 4// scrolls it like a ticker, but touch/drag stays enabled so it can still 5// be flicked by hand; autoplay resumes after the drag. 6// Rebuilt on breakpoint change so rotating / resizing switches modes. 7document.addEventListener("DOMContentLoaded", function () { 8 var el = document.querySelector(".hero-swiper"); 9 if (!el || typeof Swiper === "undefined") return; 10 var mq = window.matchMedia("(min-width: 761px)"); 11 var reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; 12 13 function buildHeroCarousel() { 14 if (el.swiper) el.swiper.destroy(true, true); 15 if (mq.matches) { 16 new Swiper(el, { 17 slidesPerView: "auto", 18 spaceBetween: 13, 19 loop: true, 20 speed: 500, 21 watchOverflow: false, 22 allowTouchMove: true, 23 navigation: { prevEl: "#heroCarPrev", nextEl: "#heroCarNext" }, 24 }); 25 } else { 26 new Swiper(el, { 27 slidesPerView: "auto", 28 spaceBetween: 8, 29 loop: true, 30 // 2026/08/06 SPï¼å·¦ç«¯å¯ãã§ã¯ãªãä¸å¤®ã«ã¹ã©ã¤ããé ç½®ï¼å·¦å³ã«é£ãè¦ãï¼ 31 centeredSlides: true, 32 allowTouchMove: true, 33 grabCursor: true, 34 speed: reduce ? 600 : 4000, 35 freeMode: { enabled: true, momentum: true }, 36 autoplay: reduce 37 ? false 38 : { delay: 0, disableOnInteraction: false, pauseOnMouseEnter: false }, 39 }); 40 } 41 } 42 buildHeroCarousel(); 43 if (mq.addEventListener) mq.addEventListener("change", buildHeroCarousel); 44 else if (mq.addListener) mq.addListener(buildHeroCarousel); 45}); 46 47// Merit 03: airplane-window photo carousel â autoplays and loops. 48// ~4 slides show so the next window peeks in and fades out via the 49// right-edge mask. Continuous "conveyor" autoplay (delay:0 + freeMode). 50document.addEventListener("DOMContentLoaded", function () { 51 var el = document.querySelector(".service-windows-swiper"); 52 if (!el || typeof Swiper === "undefined") return; 53 var reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; 54 new Swiper(el, { 55 slidesPerView: 1.6, 56 spaceBetween: 12, 57 loop: true, 58 grabCursor: true, 59 speed: reduce ? 800 : 4500, 60 freeMode: { enabled: true, momentum: false }, 61 autoplay: reduce 62 ? false 63 : { delay: 0, disableOnInteraction: false, pauseOnMouseEnter: true }, 64 breakpoints: { 65 // tablet (768â991): show ~3 larger windows instead of 4 cramped ones 66 768: { slidesPerView: 3, spaceBetween: 16 }, 67 992: { slidesPerView: 4, spaceBetween: 20 }, 68 }, 69 }); 70}); 71 72// QA: accordion toggle (flips chevron / aria-expanded) 73(function () { 74 document.querySelectorAll(".qa-trigger").forEach(function (btn) { 75 btn.addEventListener("click", function () { 76 var expanded = btn.getAttribute("aria-expanded") === "true"; 77 btn.setAttribute("aria-expanded", String(!expanded)); 78 }); 79 }); 80})(); 81 82// å£åº§éè¨ã¾ã§ã®æµã: draw the decorative line fan when it scrolls into view 83(function () { 84 var lines = document.querySelector(".jal-lines"); 85 var card = document.querySelector(".jal-card"); 86 if (!lines || !card) return; 87 if (!("IntersectionObserver" in window)) { 88 lines.classList.add("is-drawn"); 89 return; 90 } 91 var io = new IntersectionObserver( 92 function (entries) { 93 entries.forEach(function (e) { 94 if (e.isIntersecting) { 95 lines.classList.add("is-drawn"); 96 io.disconnect(); 97 } 98 }); 99 }, 100 { threshold: 0.25 }, 101 ); 102 io.observe(card); 103})(); 104 105// 2026/08/06 ã¤ã³ããåç»ãæå¾ã¾ã§åçãã¦ãããã§ã¼ãã¢ã¦ãã hero ã表示ããã 106// ã¿ã¤ãã¼ã§ã¯ãªã "ended" èµ·ç¹ã®ãããèªã¿è¾¼ã¿ãé ãã¦ãéä¸ã§åããªãã 107(function () { 108 var hero = document.querySelector(".hero"); 109 if (!hero) return; 110 var video = hero.querySelector(".hero-intro"); 111 var revealed = false; 112 var safetyTimer; 113 function reveal() { 114 if (revealed) return; 115 revealed = true; 116 if (safetyTimer) clearTimeout(safetyTimer); 117 hero.classList.add("is-revealed"); 118 if (video) { 119 video.classList.add("is-done"); 120 video.addEventListener("transitionend", function () { 121 if (video && video.parentNode) video.parentNode.removeChild(video); 122 }); 123 } 124 } 125 126 if (!video) { 127 reveal(); 128 return; 129 } 130
131 // 2026/08/06 reduced-motion è¨å®æã¯ã¤ã³ãããåç»ã®èªã¿è¾¼ã¿ãã¹ããã 132 if (window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches) { 133 reveal(); 134 return; 135 } 136 137 // 2026/08/06 WebKit ã¯ç»é¢å¤ã®åç»ãèªååçãããå試è¡ãããªã 138 if (hero.getBoundingClientRect().bottom <= 0) { 139 reveal(); 140 return; 141 } 142 143 // 2026/08/06 åç»ã®èå¾ã® hero ãé ãã«ãã¼ãæå¹åãJS ç¡å¹æã« hero ãé ããªãããJSå´ã§ä»ä¸ 144 hero.classList.add("is-intro"); 145 146 // 2026/08/06 Safari 㯠muted ã屿§ã§ãªãããããã£ã§ã®ã¿å¤å®ãç¡é³ã®é³å£°ãã©ãã¯ãããã¨èªååçãå¼¾ããã 147 video.muted = true; 148 video.defaultMuted = true; 149 // 2026/08/06 HTML ã§ã¯ãªãããã§æå®ãreduced-motion æã«èªã¿è¾¼ã¿ãèµ°ãããªããã 150 video.autoplay = true; 151 video.preload = "auto"; 152 153 // 2026/08/06 ãã¬ã¼ã¯ãã¤ã³ã㯠CSS ã® .hero-intro ã¨æããã㨠154 var mqSP = window.matchMedia ? window.matchMedia("(max-width: 767.98px)") : null; 155 function wantedSrc() { 156 return mqSP && mqSP.matches ? "/assets/video/SP_KV.mp4" : "/assets/video/PC_KV.mp4"; 157 } 158 video.src = wantedSrc(); 159 160 // 2026/08/06 ä¿éºï¼åçéå§ã¾ã§30ç§ãéå§å¾ã¯6ç§é²æãªãã§ãã³ã°ã¨ã¿ãªã 161 function armSafety(ms) { 162 if (revealed) return; 163 if (safetyTimer) clearTimeout(safetyTimer); 164 safetyTimer = window.setTimeout(reveal, ms || 30000); 165 } 166 armSafety(); 167 168 video.addEventListener("timeupdate", function () { 169 if (video.duration && video.currentTime >= video.duration) { 170 reveal(); 171 return; 172 } 173 armSafety(6000); // 2026/08/06 åçãé²ãã§ããã®ã§æéãå»¶ã°ã 174 }); 175 video.addEventListener("ended", reveal); 176 video.addEventListener("error", reveal); // 2026/08/06 åç»ãå£ãã¦ãã¦ããã¼ã¸ãå¡ããªã 177 178 var reloading = false; // 2026/08/06 èªåã®åèªã¿è¾¼ã¿ã§åçã䏿ãããéã ã true 179 var retried = false; 180 181 // 2026/08/06 WebKit ãèªååçãåæã«ä¸æãã㨠"ended" ãçºç«ããªã 182 video.addEventListener("pause", function () { 183 if (revealed || reloading || video.ended) return; 184 armSafety(1200); 185 }); 186 187 function play() { 188 var playPromise; 189 try { 190 playPromise = video.play(); 191 } catch (e) {} 192 if (playPromise && typeof playPromise.catch === "function") { 193 playPromise.catch(function (err) { 194 // 2026/08/06 èªåã®åèªã¿è¾¼ã¿ãå¾ç¶ã® play() ãå¼ãç¶ã 195 if (reloading || (err && err.name === "AbortError")) return; 196 // 2026/08/06 preload="none" ã ã¨ãã³ã¼ãåã«æåã® play() ã失æããã 197 if (!retried && video.readyState < 2) { 198 retried = true; 199 var onCanPlay = function () { 200 video.removeEventListener("canplay", onCanPlay); 201 play(); 202 }; 203 video.addEventListener("canplay", onCanPlay); 204 return; 205 } 206 reveal(); // 2026/08/06 æ¬å½ã«åçä¸å¯ï¼ä½é»åã¢ã¼ãçï¼ããµã¤ãã表示ãã 207 }); 208 } 209 } 210 211 // 2026/08/06 <video> ã¯ãªãµã¤ãºã§ source ãé¸ã³ç´ããªãããæåã§å·®ãæ¿ãã 212 if (mqSP) { 213 var onBreakpointChange = function () { 214 if (revealed || !video.parentNode) return; 215 var next = wantedSrc(); 216 if (video.getAttribute("src") === next) return; 217 // 2026/08/06 src 夿´ã§å®è¡ä¸ã® play() ã AbortError ã§ reject ããã 218 reloading = true; 219 retried = false; 220 video.src = next; 221 video.load(); 222 video.muted = true; 223 armSafety(); 224 play(); 225 window.setTimeout(function () { 226 reloading = false; 227 }, 0); 228 }; 229 if (mqSP.addEventListener) { 230 mqSP.addEventListener("change", onBreakpointChange); 231 } else if (mqSP.addListener) { 232 mqSP.addListener(onBreakpointChange); 233 } 234 } 235 236 play(); 237})(); 238 239// Circle arrows: measure each outer line so the hover "draw" animation is smooth/even 240(function () { 241 function measureArrowLines() { 242 document.querySelectorAll(".spin-arrow__ring path").forEach(function (p) {
243 try { 244 p.style.setProperty("--ring-len", p.getTotalLength()); 245 } catch (e) {} 246 }); 247 } 248 document.addEventListener("DOMContentLoaded", measureArrowLines); 249 window.addEventListener("load", measureArrowLines); 250})(); 251 252// SP carousels (Other-initiatives / Benefit Merit 02): arrows move the row one card at a time 253(function () { 254 function initCarousel(navSel, trackSel, cardSel) { 255 var nav = document.querySelector(navSel); 256 var track = document.querySelector(trackSel); 257 if (!nav || !track) return; 258 // 2026/08/07 NodeList ã®ã¾ã¾ forEach ã§ããªãç°å¢åãã«é ååï¼.service-tab ã¨åãæ±ãï¼ 259 var cards = Array.prototype.slice.call(track.querySelectorAll(cardSel)); 260 if (!cards.length) return; 261 262 // 2026/08/07 offsetLeft 㯠offsetParent åºæºã§ã¹ã¯ãã¼ã«é åã®åç¹ã¨ä¸è´ããªããã宿¸¬ãã 263 function offsetOf(card) { 264 return card.getBoundingClientRect().left - track.getBoundingClientRect().left + track.scrollLeft; 265 } 266 // 2026/08/07 scrollBy ã¯ç«¯ãè¶ãã㨠iOS å´ã®ã¹ãããã¨ç«¶åããããã忢ä½ç½®ãèªåã§ä¸¸ããã 267 // å·¦ããã£ã³ã°ã¶ãæåã§æ¢ãã¦ãå é ã«ã¼ãã®ã¬ã¿ã¼ãæ½°ããªãããã«ãã 268 function targetOf(card) { 269 var padLeft = parseFloat(window.getComputedStyle(track).paddingLeft) || 0; 270 var max = track.scrollWidth - track.clientWidth; 271 return Math.min(Math.max(offsetOf(card) - padLeft, 0), max); 272 } 273 // 2026/08/07 æã¹ã¯ã¤ãã§ãä½ç½®ãåãã®ã§ãã«ã¦ã³ã¿ãæããæ¯åã¹ã¯ãã¼ã«ä½ç½®ããç¾å¨å°ãæ±ãã 274 function currentIndex() { 275 var idx = 0; 276 var best = Infinity; 277 cards.forEach(function (card, i) { 278 var d = Math.abs(targetOf(card) - track.scrollLeft); 279 if (d < best) { 280 best = d; 281 idx = i; 282 } 283 }); 284 return idx; 285 } 286 287 nav.addEventListener("click", function (e) { 288 var btn = e.target.closest("button[data-dir]"); 289 if (!btn) return; 290 var idx = currentIndex() + (btn.dataset.dir === "prev" ? -1 : 1); 291 idx = Math.min(Math.max(idx, 0), cards.length - 1); 292 track.scrollTo({ left: targetOf(cards[idx]), behavior: "smooth" }); 293 }); 294 } 295 296 initCarousel(".brand-cards-nav", ".brand-cards", ".brand-card"); 297 initCarousel(".service-charts-nav", ".service-charts", ".service-chartcard"); 298})(); 299 300// Benefit Merit 01 tabs: sliding active pill + panel switch + prev/next arrows 301(function () { 302 document.querySelectorAll(".service-block--app").forEach(function (block) { 303 var list = block.querySelector(".service-tablist"); 304 var pill = block.querySelector(".service-tab-pill"); 305 var tabs = Array.prototype.slice.call(block.querySelectorAll(".service-tab")); 306 var panels = block.querySelectorAll(".service-feature[data-panel]"); 307 var notes = block.querySelector(".service-notes"); 308 var prevBtn = block.querySelector(".service-tabnav--prev"); 309 var nextBtn = block.querySelector(".service-tabnav--next"); 310 if (!tabs.length) return; 311 312 // hide the prev arrow on the first tab and the next arrow on the last tab; 313 // also drop the right-edge fade once the last tab is active (nothing more to scroll) 314 function updateArrows(idx) { 315 if (prevBtn) prevBtn.classList.toggle("is-hidden", idx <= 0); 316 if (nextBtn) nextBtn.classList.toggle("is-hidden", idx >= tabs.length - 1); 317 if (list) list.classList.toggle("is-end", idx >= tabs.length - 1); 318 } 319 320 function activeIndex() { 321 for (var i = 0; i < tabs.length; i++) { 322 if (tabs[i].classList.contains("is-active")) return i; 323 } 324 return 0; 325 } 326 function movePill(tab) { 327 if (!pill || !tab) return; 328 pill.style.width = tab.offsetWidth + "px"; 329 pill.style.transform = "translateX(" + tab.offsetLeft + "px)"; 330 } 331 function activate(idx, scroll) { 332 var tab = tabs[idx]; 333 if (!tab) return; 334 var name = tab.dataset.tab;
335 tabs.forEach(function (t, i) { 336 var on = i === idx; 337 t.classList.toggle("is-active", on); 338 t.setAttribute("aria-selected", on ? "true" : "false"); 339 }); 340 panels.forEach(function (p) { 341 p.hidden = p.dataset.panel !== name; 342 }); 343 if (notes) notes.hidden = name !== "app"; // footnotes belong to the app tab 344 movePill(tab); 345 updateArrows(idx); 346 if (scroll && list) { 347 var l = tab.offsetLeft; 348 var r = l + tab.offsetWidth; 349 if (l < list.scrollLeft) list.scrollTo({ left: l - 16, behavior: "smooth" }); 350 else if (r > list.scrollLeft + list.clientWidth) 351 list.scrollTo({ left: r - list.clientWidth + 16, behavior: "smooth" }); 352 } 353 } 354 // click a tab -> activate it 355 tabs.forEach(function (t, i) { 356 t.addEventListener("click", function () { 357 activate(i, true); 358 }); 359 }); 360 // SP prev/next arrows -> move the active tab one step (clamped) 361 block.querySelectorAll(".service-tabnav").forEach(function (btn) { 362 btn.addEventListener("click", function () { 363 var dir = btn.classList.contains("service-tabnav--prev") ? -1 : 1; 364 var idx = activeIndex() + dir; 365 if (idx < 0) idx = 0; 366 if (idx > tabs.length - 1) idx = tabs.length - 1; 367 activate(idx, true); 368 }); 369 }); 370 // position the pill under the initial active tab (re-sync after fonts/layout/resize) 371 function sync() { 372 movePill(tabs[activeIndex()]); 373 updateArrows(activeIndex()); 374 } 375 requestAnimationFrame(sync); 376 window.addEventListener("load", sync); 377 window.addEventListener("resize", sync); 378 }); 379})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.