/* KYA Group — homepage only (loaded after tokens.css and site.css)
 *
 * Hero · free AI skills · Journal · the Douyin band · What we do. Shared pieces
 * (container, section, section-head, split, card-grid, card, panel, button, check-list, type roles) live in site.css.
 */

/* ---------- Hero ----------
   Phones, tablets and touch devices: one column, no reel. Desktop with a mouse: text left, image reel right. */

.hero-bleed { overflow-x: clip; }
/* The hero's lower edge fades into the free-skills band's tint (decided U441) */
.hero-bleed { background: linear-gradient(to bottom, var(--color-background) calc(100% - 15rem), var(--color-panel)); }
.hero { padding: var(--hero-space-top) 0 var(--section-space); }
.hero-copy { position: relative; z-index: var(--z-raised); max-width: var(--container-lead); }
.hero .text-lead { margin: calc(var(--spacing) * 4) 0; }
.hero-note { max-width: var(--container-measure); font-size: var(--text-small); line-height: var(--text-small--line-height); color: var(--color-muted); }
.hero-reel { display: none; }
@media (width >= 48rem) {
  .hero .text-lead { margin-top: calc(var(--spacing) * 5); }
}

@media (width >= 64rem) and (hover: hover), (width >= 64rem) and (pointer: fine) {
  .hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); align-items: center; gap: calc(var(--spacing) * 8); padding-bottom: 0; }
  .hero-copy { align-self: start; max-width: none; margin-top: calc(var(--spacing) * 10); }
  .hero .text-lead { margin-top: calc(var(--spacing) * 8); }  /* 32px, as on linear.app: the headline reads as its own block */

  /* Featured image reel. app.js sets each card's position, size and opacity every frame; the motion follows
     tasteskill.dev: descend from above the page, quarter-turn, exit right. The numbers below are the reel's own
     geometry (not layout): the lowest card never reaches below about 230px under the reel's centre, so the
     negative bottom margin ends the hero about 70px below it instead of leaving the rest of the box empty. */
  .hero-reel {
    display: block; position: relative; top: -65px; height: clamp(560px, 82vh, 900px);
    margin-bottom: calc(235px - clamp(560px, 82vh, 900px) / 2);
    perspective: 3400px; touch-action: pan-y; user-select: none; -webkit-user-select: none; cursor: grab;
  }
  .hero-reel:active { cursor: grabbing; }
}
.reel-plane { position: absolute; inset: 0; transform-style: preserve-3d; transform: rotateX(3deg) rotateY(-4deg); }
.reel-card { position: absolute; left: 50%; top: 50%; width: 62%; opacity: 0; pointer-events: none; will-change: transform, opacity; }
.reel-card img { border-radius: var(--radius-2xl); box-shadow: var(--shadow-float); }
@media (prefers-reduced-motion: reduce) {
  .hero-reel, .hero-reel:active { cursor: default; }  /* dragging is off */
}

/* ---------- Free AI skills ----------
   One column: eyebrow, text, featured skills, button. Desktop with a mouse: text left, skills right (as
   tasteskill.dev's "What is new in v2"); the eyebrow sits alone in the first row so the first card lines up
   with the headline, and the button closes the text column level with the last card. */

.skills-inner { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-areas: "eyebrow" "copy" "list" "cta"; align-items: start; }
.skills-inner > .eyebrow { grid-area: eyebrow; }
.skills-copy { grid-area: copy; max-width: var(--container-lead); margin-bottom: var(--block-gap); }
.skills-copy h2 { margin-bottom: var(--gap-heading); }
.skill-types { grid-area: list; display: grid; gap: var(--grid-gap); max-width: var(--container-lead); margin: 0; padding: 0; list-style: none; }
.skills-cta { grid-area: cta; justify-self: start; }

.skill-steps { margin: var(--gap-text) 0 0; padding: 0; list-style: none; counter-reset: step; }
.skill-steps li { position: relative; margin-top: var(--gap-list); padding-left: calc(var(--spacing) * 10); counter-increment: step; }
.skill-steps li::before {
  content: counter(step); position: absolute; left: 0; top: 1px; width: calc(var(--spacing) * 6); height: calc(var(--spacing) * 6);
  border-radius: var(--radius-full); background: var(--color-surface); color: var(--color-accent);
  font-size: var(--text-caption); font-weight: var(--font-weight-semibold); line-height: calc(var(--spacing) * 6); text-align: center;
}
.skill-steps strong { display: block; font-weight: var(--font-weight-semibold); }
.skill-steps span { font-size: var(--text-small); color: var(--color-muted); }

.skill-types li { padding: var(--card-pad-sm) var(--card-pad); border: 1px solid var(--color-line); border-radius: var(--radius-2xl); background: var(--color-surface); }
.skill-types .tag { margin-bottom: calc(var(--spacing) * 2); }
.skill-types .text-title { display: block; margin-bottom: calc(var(--spacing) * 2); }
.skill-types small { display: block; font-size: var(--text-body); line-height: var(--text-small--line-height); color: var(--color-muted); }

@media (width >= 64rem) and (hover: hover), (width >= 64rem) and (pointer: fine) {
  .skills-inner {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); grid-template-rows: auto auto 1fr;
    grid-template-areas: "eyebrow ." "copy list" "cta list"; column-gap: var(--column-gap);
  }
  .skills-copy { max-width: none; margin-bottom: 0; }
  .skills-copy > p { max-width: var(--container-lead); }
  /* First card level with the headline's capitals; when the text column is the taller one, the list stretches and
     spreads its cards so the last one still ends level with the button. */
  .skill-types { align-self: stretch; align-content: space-between; max-width: none; margin-top: calc(var(--text-headline) * .2); }
  .skills-cta { align-self: end; }  /* bottom level with the last card */
}

/* ---------- What we do (one section, U489; option a, U503) ----------
   The AI copy left, a real example (the multichannel platform) in the panel right. */

.service-copy > p { max-width: var(--container-measure); color: var(--color-muted); }
.panel-label { margin-bottom: calc(var(--spacing) * 6); color: var(--color-faint); }
.example-panel .text-title { margin-bottom: var(--gap-heading); }
.example-panel p { max-width: var(--container-measure); font-size: var(--text-small); line-height: var(--text-small--line-height); color: var(--color-muted); }
.example-panel p + .text-link { margin-top: var(--gap-action); }
.example-panel .text-link { color: var(--color-accent-hover); }   /* 5.36:1 on the panel (the plain accent is 4.11:1) */

/* The Douyin band's services, side by side (not steps). Q32: rows split by hairlines inside the panel, not boxes in it
   (no card in a card, gate 135; as the AI workflows page's steps, U557). Pending client review. */
.service-grid { display: grid; column-gap: var(--grid-gap); margin: 0; padding: 0; list-style: none; }
.service-grid li { padding: calc(var(--spacing) * 4) 0; border-top: 1px solid var(--color-line); color: var(--color-text); }
.service-grid li:first-child { padding-top: 0; border-top: 0; }
.service-grid li:last-child { padding-bottom: 0; }
.service-grid strong { display: block; font-weight: var(--font-weight-medium); }
.service-grid small { display: block; margin-top: calc(var(--spacing) * 1); font-size: var(--text-caption); line-height: var(--text-caption--line-height); color: var(--color-faint); }
@media (width >= 48rem) {
  .service-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .service-grid li:nth-child(2) { padding-top: 0; border-top: 0; }
  .service-grid li:nth-last-child(2):nth-child(odd) { padding-bottom: 0; }
}

/* ---------- Journal ----------
   White, with a hairline in the teal tint where it meets the skills band (U486, U487; option A, U503): eyebrow 5.64:1,
   heading 16.3:1. Q12: "View all articles" keeps the darker accent (5.97:1 here). */
.journal { background: var(--color-background); color: var(--color-ink); border-top: 1px solid var(--color-accent-line); }
.journal .view-all { color: var(--color-accent-hover); }

/* ---------- Added U483: the three featured skills are one link each, as a whole ----------
   As the library cards (skills.css, U468): the name's link covers the card with its ::after; hover gives the border
   the accent and underlines the name; the focus ring goes round the whole card where :has() works. */
.skill-types li { position: relative; }
.skill-types .text-title a::after { content: ""; position: absolute; inset: 0; }
@media (hover: hover) {
  .skill-types li:hover { border-color: var(--color-accent); }
  .skill-types li:hover .text-title a { text-decoration: underline; }
}
@supports selector(:has(*)) {
  .skill-types li:has(.text-title a:focus-visible) { outline: 3px solid var(--color-focus); outline-offset: 5px; }
  .skill-types .text-title a:focus-visible { outline: none; }
}

/* ---------- Cross-border e-commerce: the Douyin band (decided U436–U457, U527) ----------
   A navy ground runs from the top of the section, behind the heading, down through the ring stage and the services to
   the section's bottom, fading to the page colour with eased ends (U446, U448; the colours are derived from the navy in
   OKLCH by design/douyin/build_home_placement.py, which also writes them into douyin-ring.js). The livestream photo sits
   on a slab card at the top right, level with the heading (U445, U447–U449); the light ring runs edge to edge (U450). */
.douyin-band { position: relative; isolation: isolate; padding-block: 0; }
.ring-band {
  position: relative; padding-top: var(--section-space);
  --ring-bg: var(--color-footer); --ring-text: var(--color-footer-text); --ring-muted: var(--color-footer-muted);
  --ring-shadow: 0 1px 12px color-mix(in srgb, var(--color-footer) 90%, transparent);
  background: var(--ring-bg); color: var(--ring-text);
}
.ring-band :is(h2, .section-head > p:not(.eyebrow)) { color: var(--ring-text); }
.ring-band .eyebrow { color: var(--ring-muted); }
.ring-band .section-head { position: relative; }
.ring-band .section-head > h2 { max-width: calc(68% - 2rem); }
.ring-band .section-head > p:not(.eyebrow) { max-width: min(var(--container-lead), calc(68% - 2rem)); }
.band-fade { position: relative; margin-top: var(--block-gap); padding-bottom: var(--section-space);
  background: var(--gradient-douyin-ground); color: var(--ring-text); }
.ring-stage { --stage-h: clamp(26rem, 42vw, 40rem); display: block; position: relative; container-type: inline-size; height: var(--stage-h); margin: 0; overflow: clip; }
.band-services { margin-top: var(--block-gap); color: var(--color-text); }   /* the ground's white text stops at the services panel */

/* The photo card: a slab with a lit bevel and stacked edges, tilted back (U448). card-tilt.js turns it toward the pointer
   (U449). On hover (desktop mouse only) it also lifts and its shadow grows, as on tasteskill.dev (.5 s, ease-out): the
   assistant's pick after U447, kept by the client (U578) */
.ring-card { position: absolute; top: 0; right: 0; z-index: var(--z-raised); width: 32%; perspective: 1400px; filter: drop-shadow(var(--shadow-slab));
  transition: translate var(--dur-lift) var(--ease-lift), scale var(--dur-lift) var(--ease-lift), filter var(--dur-lift) var(--ease-lift); }
.card-slab { position: relative; transform-style: preserve-3d;
  transform: translate3d(var(--shift-x, 0px), var(--shift-y, 0px), 0) rotateY(calc(-12deg + var(--tilt-y, 0deg))) rotateX(calc(5deg + var(--tilt-x, 0deg))); }
.card-face { position: relative; padding: calc(var(--spacing) * 1.5); border-radius: calc(var(--radius-2xl) + var(--spacing)); background: linear-gradient(150deg, var(--color-slab-light), var(--color-slab-mid) 55%, var(--color-slab-dark)); }
.card-face > picture > img { display: block; width: 100%; max-width: none; height: auto; border-radius: calc(var(--radius-2xl) - var(--spacing) / 2); }
.card-face > picture { display: contents; }   /* U623: the <picture> only picks the file (none on phones); the img lays out as before */
.card-face::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: var(--shadow-slab-bevel); }
.card-edge { display: block; position: absolute; inset: 0; border-radius: calc(var(--radius-2xl) + var(--spacing)); transform: translateZ(calc(var(--d) * -1.2px));
  background: color-mix(in srgb, var(--color-slab-dark) calc(var(--d) * 10%), var(--color-slab-edge)); }
/* the same query string as card-tilt.js: layout.md §9's width plus capability, narrowed to hover only because a :hover
   effect must sit in a hover query (gate 95); not the full desktop-with-a-mouse query */
@media (width >= 64rem) and (hover: hover) {
  .ring-card:hover { translate: 0 -10px; scale: 1.04; filter: drop-shadow(var(--shadow-slab-lift)); }
}
@media (prefers-reduced-motion: reduce) { .ring-card { transition: none; } }

/* The badge sits on the photo's bottom-right corner, outside the photo's must-show region */
.ring-badge { position: absolute; right: -1.5rem; bottom: -1.75rem; z-index: var(--z-raised); display: grid; place-content: center; width: 6.5rem; aspect-ratio: 1; margin: 0;
  border-radius: var(--radius-full); background: var(--color-badge); color: var(--color-footer); text-align: center; box-shadow: 0 0 0 4px var(--color-badge-ring), var(--shadow-float); }
.ring-badge b { font-size: var(--text-title); line-height: 1; font-variant-numeric: tabular-nums; font-weight: var(--font-weight-semibold); color: var(--color-accent-hover); }   /* 5.65:1 on the badge; the plain accent is 4.34:1 (U501 cross-review) */
.ring-badge small { margin-top: var(--spacing); font-size: var(--text-caption); line-height: 1.25; font-weight: var(--font-weight-semibold); }

/* The ring: the canvas runs the stage's full width; the route list and the words are page text over it */
.ring-box { position: relative; z-index: var(--z-raised); height: 100%; }   /* above the photo card (same level, later in the page) */
.ring-canvas { position: absolute; left: calc(50% - 50cqw); top: 0; width: 100cqw; height: 100%; }   /* the stage's full width (container units) */
.no-webgl .ring-canvas { display: none; }
.ring-route { position: absolute; left: 0; top: 10%; z-index: var(--z-raised); text-shadow: var(--ring-shadow); }
.ring-kicker { margin: 0 0 calc(var(--spacing) * 3); font-size: var(--text-label); line-height: var(--text-label--line-height); letter-spacing: var(--text-label--letter-spacing); font-weight: var(--text-label--font-weight); color: var(--ring-muted); }
.ring-route ul { margin: 0; padding: 0; list-style: none; display: grid; gap: calc(var(--spacing) * 2); font-size: var(--text-small); font-weight: var(--font-weight-medium); }
.ring-route li::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-right: calc(var(--spacing) * 3); border-radius: var(--radius-full); background: var(--color-route-dot); vertical-align: middle; }
/* Q50, tablets only (48–64rem): there the ribbon's upper arc runs under the list's last lines (white on the bright
   ribbon measured 1.16–2.8:1 at 768–900 px). Each line gets the ring words' own backing: the tight halo round the letters
   and the soft pool behind it, in the band's navy (--ring-bg); over the whole loop at 768–990 px every line now
   measures 10.1:1 or more (6.3:1 or more even with the letter halo left out; software rendering, p90 backing). Phones have no ring, and from 1024 px every line already stays above 6.9:1, so both are unchanged.
   Not while the list has switched to ink (.on-light). Pending client review. */
@media (width >= 48rem) and (width < 64rem) {
  .ring-route:not(.on-light) li { position: relative; --h: var(--ring-bg); text-shadow: 0 0 1px var(--h), 0 0 2px var(--h), 0 0 4px var(--h), 0 0 8px var(--h); }
  .ring-route:not(.on-light) li::after { content: ""; position: absolute; inset: -2.5em -4em; z-index: -1;
    background: radial-gradient(closest-side, var(--h), color-mix(in srgb, var(--h) 88%, transparent) 20%, color-mix(in srgb, var(--h) 62%, transparent) 40%,
      color-mix(in srgb, var(--h) 32%, transparent) 60%, color-mix(in srgb, var(--h) 11%, transparent) 80%, transparent); }
}
/* The route list, on a part of the ground the fade has turned light, switches to ink (set by douyin-ring.js, whichever
   of light and ink reads better there, U446) */
.ring-stage .on-light { --ring-text: var(--color-ink); --ring-muted: var(--color-ink); --ring-shadow: 0 0 10px var(--color-background); color: var(--ring-text); }
.ring-stage .on-mid { --ring-muted: var(--ring-text); }
/* The words on the ring stay readable where the ribbon's light runs behind them (U455, U488): each word has its own
   shade (--ring-halo, set by douyin-ring.js as the word moves: the ground's colour at the word's height, a little darker
   and never lighter than L* 32), drawn as a tight halo round the letters and a wide, soft pool behind the word; every
   word keeps about 7:1 or more through the loop. The pill, which sits on the ribbon, keeps its own navy plate. */
.ring-label { position: absolute; z-index: var(--z-raised); transform: translate(-50%, -50%); font-size: var(--text-small); font-weight: var(--font-weight-medium); white-space: nowrap; text-shadow: var(--ring-shadow); }
.ring-label:not(.is-pill) { --h: var(--ring-halo, var(--ring-bg)); text-shadow: 0 0 1px var(--h), 0 0 2px var(--h), 0 0 4px var(--h), 0 0 8px var(--h); }
.ring-label:not(.is-pill)::before { content: ""; position: absolute; inset: -2.5em -4em; z-index: -1;
  background: radial-gradient(closest-side, var(--h), color-mix(in srgb, var(--h) 88%, transparent) 20%, color-mix(in srgb, var(--h) 62%, transparent) 40%,
    color-mix(in srgb, var(--h) 32%, transparent) 60%, color-mix(in srgb, var(--h) 11%, transparent) 80%, transparent); }
.ring-label.is-pill { padding: calc(var(--spacing) * 2) calc(var(--spacing) * 5); border: 1px solid color-mix(in srgb, var(--ring-text) 35%, transparent); border-radius: var(--radius-full); background: color-mix(in srgb, var(--ring-bg) 82%, transparent); color: var(--ring-text); font-size: var(--text-body); backdrop-filter: blur(var(--blur-pill)); }
/* Static fallback (new-F4; motion.md §10, gates 45 and 79), pending client review. Until douyin-ring.js has drawn the
   ring (no JS, no WebGL, a shader error, or before the script runs), a still of the ring shows in the canvas's place and
   the words stand where the script puts them on that same frame (its reduced-motion frame). --ring-s is the script's
   fit as a length: the ring's extent over its whole motion (6.5565 × 2.7698 in its own units) fills at most 96% of the
   stage's width and 84% of its height (fit() in douyin-ring.js: fillX, fillY). The still covers 6.7038 such units
   across (its 1230 × 552 px, taken at 1440 px wide and 1x, where the unit was 183.48 px), centred as the ring is.
   Each word's --lx, --ly and --px, --py are in index.astro. Without the script the words keep the navy halo
   (--ring-bg), not the ground's shade. */
.ring-box { --ring-s: min(0.96 * 100cqw / 6.5565, 0.84 * var(--stage-h) / 2.7698); }
.ring-poster { position: absolute; left: 50%; top: 50%; width: calc(var(--ring-s) * 6.7038); max-width: none; height: auto; translate: -50% -50%; pointer-events: none; }
.ring-stage.ring-on .ring-poster { display: none; }
.ring-stage.ring-wait .ring-poster { display: none; }   /* U623: while douyin-ring.js is on its way (index.astro) */
.ring-stage:not(.ring-on) .ring-label { left: calc(50% + var(--ring-s) * var(--lx) + var(--px, 0em)); top: calc(50% + var(--ring-s) * var(--ly) + var(--py, 0em)); }

/* Phones (U527): the photo card and the light ring are not shown (hard to look at on a small screen); the heading, text
   and services panel stay. Since U623 phones also download neither: index.astro loads douyin-ring.js only from 48rem
   and offers the photo and the ring's still no file below 48rem. */
@media (width < 48rem) {
  .ring-band .section-head { display: flex; flex-direction: column; }
  .ring-band .section-head > :is(h2, p:not(.eyebrow)) { max-width: none; }
  .ring-stage, .ring-card { display: none; }
}
