/* ==========================================================================
   AIU AI Workshop — deck styles for reveal.js
   Each slide is a fixed 1920×1080 canvas (.slide). Content uses inline styles,
   so most edits happen directly in index.html.
   ========================================================================== */

/* ---------- Palette (reuse these when you add content) ----------
   Navy (AIU primary) #17365F · Dark #0B1C36 · Light bg #EFF3F8
   Blue #2563C9 · Bright blue #2E8BE6 · Cyan accent #5EE0F5
   Text on dark #F3F4FA · Muted on dark #A9B0C6 · Muted on light #4B5168   */

/* reveal.css (loaded later) paints .reveal-viewport white; keep letterbox areas navy */
html, body, body.reveal-viewport { background: #0B1C36; }
.reveal { font-family: 'Inter', Arial, sans-serif; }
/* html prefix: outranks reveal.css (loaded later), which centres .reveal .slides */
html .reveal .slides { text-align: left; }
.reveal .slides > section { padding: 0; width: 1920px; height: 1080px; }

/* The slide canvas */
.reveal .slide { position: relative; width: 1920px; height: 1080px; overflow: hidden; box-sizing: border-box; }
.reveal .slide * { margin: 0; box-sizing: border-box; }
.reveal .slide h1, .reveal .slide h2, .reveal .slide h3 { text-transform: none; text-shadow: none; }
.reveal .slide img, .reveal .slide video, .reveal .slide iframe { max-width: none; max-height: none; margin: 0; border: 0; display: block; }
.reveal .slide table { border-collapse: collapse; width: 100%; }
.reveal .slide th, .reveal .slide td { padding: 0.35em 0.6em; border: 1px solid #E3E5EE; text-align: left; }
.reveal .slide ul, .reveal .slide ol { padding-left: 1.2em; }

/* Icons (inline SVG, inherit color from the wrapper) */
.reveal .slide .xi { display: inline-flex; align-items: center; justify-content: center; flex: none; }
.reveal .slide .xi svg { width: 62%; height: 62%; }

/* Shapes */
.reveal .slide .xs { display: block; flex: none; }
.reveal .slide .xs-ellipse { border-radius: 50%; }
.reveal .slide .xs-diamond { clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }
.reveal .slide .xs-arrow-right { clip-path: polygon(0 30%, 60% 30%, 60% 0, 100% 50%, 60% 100%, 60% 70%, 0 70%); }
.reveal .slide .xs-arrow-left  { clip-path: polygon(100% 30%, 40% 30%, 40% 0, 0 50%, 40% 100%, 40% 70%, 100% 70%); }

/* ---------- Motion system ----------
   One easing for everything (fast launch, soft landing), longer travel,
   blur-to-sharp for depth. Overrides reveal.js's stock 0.2s fragment moves. */
:root { --ease-out: cubic-bezier(.16, 1, .3, 1); --t-move: .9s; --t-fade: .6s; }

.reveal .slides section .fragment.fade-up,
.reveal .slides section .fragment.fade-down,
.reveal .slides section .fragment.fade-left,
.reveal .slides section .fragment.fade-right,
.reveal .slides section .fragment.fade-in,
.reveal .slides section .fragment.zoom-in,
.reveal .slides section .fragment.fade-in-then-out {
  filter: blur(8px);
  transition: opacity var(--t-fade) var(--ease-out), transform var(--t-move) var(--ease-out),
              filter var(--t-fade) var(--ease-out), visibility var(--t-fade);
}
.reveal .slides section .fragment.fade-up    { transform: translate3d(0, 64px, 0) scale(.98); }
.reveal .slides section .fragment.fade-down  { transform: translate3d(0, -64px, 0) scale(.98); }
.reveal .slides section .fragment.fade-right { transform: translate3d(-80px, 0, 0); }
.reveal .slides section .fragment.fade-left  { transform: translate3d(80px, 0, 0); }
.reveal .slides section .fragment.zoom-in    { transform: scale(.86); }
.reveal .slides section .fragment.fade-up.visible,
.reveal .slides section .fragment.fade-down.visible,
.reveal .slides section .fragment.fade-left.visible,
.reveal .slides section .fragment.fade-right.visible,
.reveal .slides section .fragment.fade-in.visible,
.reveal .slides section .fragment.zoom-in.visible,
.reveal .slides section .fragment.fade-in-then-out.current-fragment { transform: none; filter: none; }

/* Headline mask reveal: js/deck.js wraps each word of a slide title in
   <span class="mw"><span>word</span></span>; words rise out of an invisible line. */
.reveal .slide .mw { display: inline-block; overflow: hidden; vertical-align: top;
  padding: .06em 0 .16em; margin: -.06em 0 -.16em; }
.reveal .slide .mw > span { display: inline-block; transform: translate3d(0, 110%, 0);
  transition: transform var(--t-move) var(--ease-out); }
.reveal .slides section.present .mw > span,
.reveal .slides section.mw-static .mw > span,
.reveal.overview .mw > span, html.print-pdf .mw > span { transform: none; }
.reveal .slides section.mw-static .mw > span { transition: none; }

/* Respect the OS "reduce motion" setting: keep the fades, drop movement and blur */
@media (prefers-reduced-motion: reduce) {
  .reveal .slides section .fragment.fade-up, .reveal .slides section .fragment.fade-down,
  .reveal .slides section .fragment.fade-left, .reveal .slides section .fragment.fade-right,
  .reveal .slides section .fragment.fade-in, .reveal .slides section .fragment.zoom-in,
  .reveal .slides section .fragment.fade-in-then-out { transform: none; filter: none; }
  .reveal .slide .mw > span { transform: none; transition: none; }
}

/* ---------- Custom fragment effects ---------- */
/* pop: scale in with a little overshoot */
.reveal .slides section .fragment.pop { opacity: 0; transform: scale(0.6); visibility: hidden;
  transition: opacity .35s ease, transform .45s cubic-bezier(.34,1.56,.64,1), visibility .35s; }
.reveal .slides section .fragment.pop.visible { opacity: 1; transform: none; visibility: inherit; }
/* pop-then-out: pops in, disappears on the next click (moving highlight) */
.reveal .slides section .fragment.pop-then-out { opacity: 0; visibility: hidden; transform: scale(0.92);
  transition: opacity .3s ease, transform .4s cubic-bezier(.34,1.56,.64,1), visibility .3s; }
.reveal .slides section .fragment.pop-then-out.current-fragment { opacity: 1; visibility: inherit; transform: none; }

/* ---------- Emphasis: a light loop runs around each highlighted (.emph) frame ----------
   The frame's own border fades to a faint outline; ::before draws a comet of light on the
   border (a rotating conic gradient, masked to a ring) and ::after is its blurred glow.
   It pulses once on arrival and the light keeps circling while the highlight is shown. */
@property --emph-a { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
/* Colours: a frame around a coloured element takes that element's palette (hl-* class set in
   index.html), so the light never clashes with the fill; other frames stay cyan and blue. */
.reveal .slide .emph { --hl-light: #5EE0F5; --hl-dark: #2E8BE6; }
.reveal .slide .emph.hl-orange { --hl-light: #FBB54A; --hl-dark: #E5640E; }
.reveal .slide .emph.hl-purple { --hl-light: #C49BFA; --hl-dark: #6A2BD9; }
.reveal .slide .emph.hl-blue   { --hl-light: #6FCBF4; --hl-dark: #1E78D4; }
.reveal .slide .emph.hl-red    { --hl-light: #FF9AA6; --hl-dark: #D8264A; }
@keyframes emph-pulse {
  0%, 100% { box-shadow: 0 0 36px color-mix(in srgb, var(--hl-light) 45%, transparent); }
  50%      { box-shadow: 0 0 70px color-mix(in srgb, var(--hl-light) 95%, transparent),
                         0 0 0 6px color-mix(in srgb, var(--hl-light) 18%, transparent); }
}
@keyframes emph-run { to { --emph-a: 360deg; } }
.reveal .slide .emph { border-color: color-mix(in srgb, var(--hl-light) 30%, transparent) !important; }
.reveal .slide .emph::before, .reveal .slide .emph::after {
  content: ""; position: absolute; inset: -4px; padding: 4px; border-radius: inherit; pointer-events: none;
  background: conic-gradient(from var(--emph-a), transparent 0deg 230deg,
              color-mix(in srgb, var(--hl-dark) 60%, transparent) 290deg,
              var(--hl-light) 340deg, #FFFFFF 357deg, transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
.reveal .slide .emph::after { inset: -10px; padding: 10px; filter: blur(9px); opacity: .9; }
.reveal .slides section .fragment.emph.visible { animation: emph-pulse 1.3s ease-in-out 1; }
.reveal .slides section .fragment.emph.visible::before,
.reveal .slides section .fragment.emph.visible::after { animation: emph-run 2.6s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  .reveal .slides section .fragment.emph.visible::before { animation: none; background: var(--hl-light); }
  .reveal .slides section .fragment.emph.visible::after { animation: none; display: none; }
}

/* ---------- Demo cursor: glides to each highlighted (.emph) element and clicks it ----------
   js/deck.js moves it; while .reveal has .cursor-clicking, the highlight waits for the click. */
.reveal .slide .demo-cursor { position: absolute; left: 0; top: 0; z-index: 50; width: 64px; height: 64px;
  pointer-events: none; opacity: 0; filter: drop-shadow(0 6px 10px rgba(0, 0, 0, .35));
  transition: transform .7s cubic-bezier(.65, 0, .35, 1), opacity .5s ease; }
.reveal .slide .demo-cursor.on { opacity: 1; }
.reveal .slide .demo-cursor svg { display: block; width: 100%; height: 100%; transform-origin: 18% 10%;
  transition: transform .12s ease; }
.reveal .slide .demo-cursor.click svg { transform: scale(.8); }
.reveal .slide .demo-cursor .ring { position: absolute; left: 11px; top: 7px; width: 96px; height: 96px;
  border: 3px solid #5EE0F5; border-radius: 50%; opacity: 0; transform: translate(-50%, -50%) scale(.2); }
.reveal .slide .demo-cursor.click .ring { animation: cursor-ring .6s cubic-bezier(.16, 1, .3, 1); }
@keyframes cursor-ring {
  from { opacity: .95; transform: translate(-50%, -50%) scale(.2); }
  to   { opacity: 0;   transform: translate(-50%, -50%) scale(1.3); }
}
.reveal.cursor-clicking .slides section .fragment.pop.emph.visible,
.reveal.cursor-clicking .slides section .fragment.pop-then-out.emph.current-fragment {
  transition-delay: .75s; animation-delay: .75s;
}

/* ---------- Keyword storm (slide 14): words pop in until they cover the slide ----------
   Each word sits in a .kw-box (horizontal, or vertical with .v; .up reads bottom to top);
   js/deck.js sizes the word to fill its box. Each .kw has its own start time in --d. */
.reveal .slide .kw-box { position: absolute; display: flex; align-items: center; white-space: nowrap; }
.reveal .slide .kw-box.v { writing-mode: vertical-rl; }
.reveal .slide .kw-box.v.up { transform: rotate(180deg); }
.reveal .slide .kw-box.main { z-index: 2; }   /* above the scrim */
.reveal .slide .kw { display: inline-block; font-family: 'Plus Jakarta Sans', Arial, sans-serif; font-weight: 800;
  line-height: .98; letter-spacing: -.02em; text-transform: uppercase;
  transition: opacity .6s var(--ease-out), filter .6s var(--ease-out); }
.reveal .slide .kw-white   { color: #F3F4FA; }
.reveal .slide .kw-muted   { color: #4F6A92; }
.reveal .slide .kw-soft    { color: #9EC3F0; }
.reveal .slide .kw-outline { color: transparent; -webkit-text-stroke: 2px #6F9BD6; }
.reveal .slide .kw-cyan    { color: #5EE0F5; }
.reveal .slide .kw-block   { color: #F3F4FA; background: #2E8BE6; padding-inline: .18em; }
.reveal .slide .kw-invert  { color: #0B1C36; background: #F3F4FA; padding-inline: .18em; }
/* Coloured blocks borrowed from the slide-9 arrows */
.reveal .slide .kw-b-orange { color: #FFFFFF; background: linear-gradient(90deg, #E5640E, #F7A23A); padding-inline: .18em; }
.reveal .slide .kw-b-purple { color: #FFFFFF; background: linear-gradient(90deg, #6A2BD9, #A468F5); padding-inline: .18em; }
.reveal .slide .kw-b-blue   { color: #FFFFFF; background: linear-gradient(90deg, #1E78D4, #5BBDF0); padding-inline: .18em; }
.reveal .slide .kw-b-red    { color: #FFFFFF; background: linear-gradient(90deg, #D8264A, #F7707F); padding-inline: .18em; }
@keyframes kw-pop {
  0%   { opacity: 0; transform: scale(.35); filter: blur(12px); }
  55%  { opacity: 1; transform: scale(1.12); filter: blur(0); }
  75%  { transform: scale(.97); }
  100% { opacity: 1; transform: none; filter: none; }
}
/* Camera: holds close while the centre fills, then pulls back to reveal the outer ring of words */
.reveal .slide .kw-cam { position: absolute; left: 0; top: 0; width: 1920px; height: 1080px; transform-origin: 960px 540px; }
/* 10.4s: hold to 5.2s, pull back to 60% (first ring), short pause, pull back to 42% (second ring) */
@keyframes kw-zoom {
  0%   { transform: scale(1.06); animation-timing-function: linear; }
  50%  { transform: scale(1);    animation-timing-function: cubic-bezier(.65, 0, .35, 1); }
  71%  { transform: scale(.6);   animation-timing-function: linear; }
  74%  { transform: scale(.6);   animation-timing-function: cubic-bezier(.65, 0, .35, 1); }
  100% { transform: scale(.42); }
}
.reveal .slides section.kw-storm.present .kw-cam { animation: kw-zoom 10.4s both; }
.reveal .slides section.kw-storm.present .kw { animation: kw-pop .7s cubic-bezier(.34,1.56,.64,1) var(--d) backwards; }
/* fill-mode backwards: hidden until its turn, then back to the plain style, so the dim below can apply */
/* After the click: the wall dims, the six named keywords stay lit */
.reveal .slide .kw-card { z-index: 3; }
.reveal .slides section.kw-storm:has(.kw-scrim.visible) .kw:not(.kw-main) { opacity: .14; filter: blur(2px); }
.reveal .slides section.kw-storm:has(.kw-scrim.visible) .kw-main { opacity: 1; }
/* While the facilitator talks, js/deck.js makes random words bounce (class kw-bounce on the box).
   Uses the scale property, so it adds to the box's own rotation instead of replacing it. */
@keyframes kw-bounce {
  0%   { scale: 1;    filter: none; }
  30%  { scale: 1.22; filter: brightness(1.45) drop-shadow(0 0 18px rgba(94,224,245,.6)); }
  55%  { scale: .94;  filter: none; }
  75%  { scale: 1.05; }
  100% { scale: 1; }
}
.reveal .slides section.kw-storm.present .kw-box.kw-bounce { animation: kw-bounce .7s cubic-bezier(.34,1.56,.64,1); }
@media (prefers-reduced-motion: reduce) {
  .reveal .slides section.kw-storm.present .kw { animation: none; opacity: 1; }
  .reveal .slides section.kw-storm.present .kw-cam { animation: none; transform: scale(.42); }
}

/* ---------- Part dividers: the title is written by light ----------
   js/deck.js splits each h1.light-write into letters (.lc, numbered --i) inside words (.lw).
   When the title step shows, each letter flashes white-hot with a cyan glow in turn,
   then cools to its normal colour, so the light travels along the title like a pen. */
:root { --lw-step: 45ms; }
.reveal .slides section .fragment.light-write { opacity: 0; visibility: hidden; transition: none; }
.reveal .slides section .fragment.light-write.visible { opacity: 1; visibility: inherit; }
.reveal .slide .light-write .lw { display: inline-block; white-space: nowrap; }
.reveal .slide .light-write .lc { display: inline-block; }
@keyframes light-write {
  0%   { opacity: 0; transform: scale(1.4); filter: blur(12px) brightness(3);
         text-shadow: 0 0 0 rgba(255,255,255,0), 0 0 0 rgba(94,224,245,0), 0 0 0 rgba(46,139,230,0); }
  10%  { opacity: 1; transform: scale(1); filter: blur(0) brightness(2.2);
         text-shadow: 0 0 6px #FFFFFF, 0 0 24px rgba(94,224,245,.95), 0 0 70px rgba(46,139,230,.85); }
  45%  { filter: brightness(1.25);
         text-shadow: 0 0 2px rgba(255,255,255,.6), 0 0 14px rgba(94,224,245,.55), 0 0 40px rgba(46,139,230,.35); }
  100% { opacity: 1; transform: none; filter: none;
         text-shadow: 0 0 0 rgba(255,255,255,0), 0 0 0 rgba(94,224,245,0), 0 0 0 rgba(46,139,230,0); }
}
/* Then, while the slide stays on screen, a band of light keeps running through the title:
   each loop crosses all letters in 2.4s, rests, and starts again (4s per loop). */
@keyframes light-loop {
  0%, 16%, 100% { filter: none; transform: none;
         text-shadow: 0 0 0 rgba(255,255,255,0), 0 0 0 rgba(94,224,245,0), 0 0 0 rgba(46,139,230,0); }
  5%   { filter: brightness(1.9); transform: translateY(-.03em);
         text-shadow: 0 0 6px #FFFFFF, 0 0 22px rgba(94,224,245,.9), 0 0 60px rgba(46,139,230,.7); }
}
.reveal .slides section .light-write.visible .lc {
  animation:
    light-write 1.2s cubic-bezier(.16, 1, .3, 1) calc(var(--i) * var(--lw-step)) both,
    light-loop 4s linear calc(var(--n) * var(--lw-step) + 1.4s + var(--i) * (2.4s / var(--n))) infinite; }
@media (prefers-reduced-motion: reduce) {
  .reveal .slides section .light-write.visible .lc { animation: none; }
}

/* Live demo embed */
.reveal .slide .xe { background: #0B1C36; }

/* ---------- Floating "Materials" download button (press M to hide/show) ---------- */
/* js/deck.js puts the Materials button and the EN | ไทย switch side by side in .corner-links */
.corner-links { position: fixed; left: 16px; bottom: 16px; z-index: 40; display: flex; gap: 6px; }
.materials-link, .lang-link { display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px; font: 600 14px/1 'Inter', 'Noto Sans Thai', Arial, sans-serif; color: #F3F4FA; text-decoration: none;
  background: rgba(11,28,54,0.72); border: 1px solid rgba(255,255,255,0.22); border-radius: 999px; backdrop-filter: blur(6px); }
.materials-link:hover { background: #17365F; }
/* the language switch stands out in AIU blue */
.lang-link { background: #2E8BE6; border-color: rgba(255,255,255,0.35); }
.lang-link:hover { background: #2563C9; }
.materials-link svg { width: 16px; height: 16px; }
body.hide-materials .corner-links, .reveal.overview ~ .corner-links { display: none; }
@media print { .corner-links { display: none; } }

/* ---------- Phones and small screens ----------
   Slides are a fixed 1920x1080 canvas that reveal.js scales to fit, which suits landscape.
   In portrait, js/deck.js shows a dismissible hint to turn the phone sideways. */
.rotate-hint { position: fixed; left: 12px; right: 12px; top: 12px; z-index: 60; display: none; align-items: center; gap: 12px;
  padding: 12px 14px; font: 600 15px/1.35 'Inter', 'Noto Sans Thai', Arial, sans-serif; color: #F3F4FA; background: rgba(23,54,95,0.95);
  border: 1px solid rgba(94,224,245,0.35); border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.35); cursor: pointer; }
.rotate-hint svg { flex: none; width: 28px; height: 28px; color: #5EE0F5; }
.rotate-hint span { flex: 1; }
.rotate-hint b { color: #5EE0F5; font-weight: 600; }
@media (orientation: portrait) and (max-width: 820px) {
  body:not(.rotate-hint-off) .rotate-hint { display: flex; }
}
@media (max-width: 900px), (max-height: 500px) {
  .corner-links { left: 8px; bottom: 8px; }
  .materials-link, .lang-link { padding: 6px 10px; font-size: 12px; }
  .materials-link svg { width: 13px; height: 13px; }
}
@media print { .rotate-hint { display: none !important; } }
