/* 3D hero component styles (site bundle). */
/* Every selector here is a .hero / .hero-* class, so this can't restyle the host page
   (the site uses Bootstrap 3). Colours are custom properties scoped to the hero. Sizes are
   px, since Bootstrap 3 sets the root font size to 10px. export.py appends the bundle's own
   rules: aspect ratios, which variant's layers show, and which label goes with which product. */
.hero, .hero-card {
  --hero-ink: #1d1f23;
  --hero-muted: #5d6068;
  --hero-bg: #e9e8e4;
  --hero-accent: #1f6feb;
  --hero-card: #ffffff;
  --hero-chip: rgba(29, 31, 35, 0.92);
}

.hero, .hero *, .hero-card, .hero-card * { box-sizing: border-box; }

/* ---- the hero box: reserved aspect ratio (set per bundle), so no layout shift ---- */
.hero { position: relative; display: block; width: 100%; margin: 0; padding: 0; line-height: 1.3; font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; border-radius: 14px; overflow: hidden; background: var(--hero-bg); isolation: isolate; touch-action: pan-y; container: hero / inline-size; }
.hero picture { position: absolute; inset: 0; }
.hero-poster { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: cover; }

/* ---- the poster's products: sprites from the atlas over the plate (floor + props) ---- */
.hero-layer { position: absolute; inset: 0; pointer-events: none; }
.hero-layer i { position: absolute; display: block; background-image: var(--atlas); background-repeat: no-repeat; }
.hero-pr { transform-origin: 50% 90%; }

/* ---- live 3D: drawn under the poster, then faded in on top of the identical frame ---- */
.hero-canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; display: block; opacity: 0; transition: opacity 0.35s ease; outline: none; }
.hero.is-3d .hero-canvas { opacity: 1; touch-action: none; }
.hero.is-3d picture, .hero.is-3d .hero-layer { visibility: hidden; transition: visibility 0s 0.4s; }
.hero.is-3d .hero-hotspots, .hero.is-3d .hero-tips { display: none; }

/* ---- poster hotspots: real links over each product ---- */
.hero-hotspots { position: absolute; inset: 0; }
.hero-hs { position: absolute; display: block; text-decoration: none; border-radius: 12px; outline: none; transition: box-shadow 0.15s; }
.hero-hs:hover, .hero-hs:focus-visible { box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.95), 0 0 0 4px var(--hero-accent), 0 0 18px 4px rgba(31, 111, 235, 0.35); }

/* ---- rank badges: on the poster, and kept on in 3D (hero3d.js moves them with the products) ---- */
.hero-badges { position: absolute; inset: 0; pointer-events: none; }
.hero-badge { position: absolute; transform: translate(-50%, -50%); min-width: 26px; height: 26px; padding: 0 7px; border-radius: 13px; background: var(--hero-chip); color: #fff; font: 700 13px/26px system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; text-align: center; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25); }

/* ---- the product label: one fixed spot, top right of the hero, so it never covers the products.
   Compact: name and best-for on the left, the button on the right (the spec line only when the
   hero is big enough to spare the room). ---- */
.hero-card { position: absolute; z-index: 4; right: 10px; top: 10px; width: max-content; max-width: min(330px, 62%); display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 10px; align-items: center; background: var(--hero-card); color: var(--hero-ink); border-radius: 10px; padding: 7px 8px 7px 11px; box-shadow: 0 6px 22px rgba(0, 0, 0, 0.2); font: 13px/1.3 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; pointer-events: auto; }
.hero-card[hidden] { display: none; }
.hero-card b, .hero-card .bf, .hero-card .ks { grid-column: 1; }
.hero-card b { display: block; font-size: 14px; }
.hero-card .bf { color: var(--hero-muted); display: block; }
.hero-card .ks { display: none; margin-top: 2px; }
.hero-card a, .hero-card .cta { grid-column: 2; grid-row: 1 / span 3; display: inline-block; padding: 6px 10px; border-radius: 7px; background: #ffd814; color: #111; font-weight: 700; white-space: nowrap; text-decoration: none; }
.hero-card a:focus-visible { outline: 3px solid var(--hero-accent); outline-offset: 2px; }
@container hero (min-width: 700px) { .hero-card .ks { display: block; } }
/* the poster's labels (CSS only: the bundle's :has() rules show the hovered product's) */
.hero-tips { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.hero-tip { pointer-events: auto; color: inherit; text-decoration: none; visibility: hidden; opacity: 0; transition: opacity 0.2s 1.2s, visibility 0s 1.4s; }
/* a label lingers ~1.2 s after the pointer leaves its product, so its button can be reached; it stays while
   hovered, and hovering another product swaps it at once (user, 2026-10-14) */
.hero:has(.hero-hs:hover) .hero-tip { transition-delay: 0s, 0s; }
.hero-tip:hover { visibility: visible; opacity: 1; transition-delay: 0s; }
@media (hover: none) { .hero-tips { display: none; } }
/* phones: the 3D card docks under the hero (an overlay would cover the products there) */
.hero-card.is-docked { position: static; width: auto; max-width: none; margin: 10px 0 18px; column-gap: 12px; padding: 9px 10px 9px 12px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.14); }
.hero-card.is-docked .ks { display: none; }

/* ---- button ---- */
.hero-3d-btn { position: absolute; right: 12px; bottom: 12px; z-index: 3; display: inline-flex; gap: 6px; align-items: center; border: 0; border-radius: 999px; padding: 8px 14px; background: rgba(255, 255, 255, 0.94); color: #1d1f23; font: 600 14px/1 system-ui, sans-serif; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18); cursor: pointer; }
.hero-3d-btn:hover { background: #fff; }
.hero-3d-btn:focus-visible { outline: 3px solid var(--hero-accent); outline-offset: 2px; }
.hero-3d-btn[disabled] { cursor: progress; opacity: 0.85; }
@media (max-width: 640px) { .hero-3d-btn { right: 8px; bottom: 8px; padding: 6px 10px; font-size: 13px; } }
/* desktops load 3D by themselves, so the pill stays out of the way until it's the reset icon
   (hero-loader.js adds .no-auto when this device won't auto-load) */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .hero:not(.no-auto) .hero-3d-btn:not(.is-reset) { visibility: hidden; }
}
/* once 3D is live the pill becomes a small reset icon (hero3d.js adds .is-reset and the icon) */
.hero-3d-btn.is-reset { right: 10px; bottom: 10px; width: 34px; height: 34px; padding: 0; justify-content: center; border-radius: 50%; background: rgba(255, 255, 255, 0.62); color: #44474e; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12); opacity: 0.8; transition: opacity 0.15s, background-color 0.15s; }
.hero-3d-btn.is-reset:hover, .hero-3d-btn.is-reset:focus-visible { opacity: 1; background: rgba(255, 255, 255, 0.95); color: #1d1f23; }
.hero-3d-btn.is-reset > :not(.hero-reset-ico) { display: none; }
/* zoom (user, 2026-10-15): + and - stacked above the reset icon, same look; a limit greys its button */
.hero-zoom { position: absolute; right: 10px; bottom: 52px; z-index: 3; display: flex; flex-direction: column; gap: 6px; }
.hero-zoom-btn { width: 34px; height: 34px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.62); color: #44474e; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12); opacity: 0.8; cursor: pointer; transition: opacity 0.15s, background-color 0.15s; }
.hero-zoom-btn:hover, .hero-zoom-btn:focus-visible { opacity: 1; background: rgba(255, 255, 255, 0.95); color: #1d1f23; }
.hero-zoom-btn:focus-visible { outline: 3px solid var(--hero-accent); outline-offset: 2px; }
.hero-zoom-btn.is-off { opacity: 0.32; cursor: default; }

/* ---- the scale key (scene.json "scale_key"; user, 2026-10-15): a flat "SCALE" card, never a 3D object.
   One white bar in inches or feet whose length matches the products at their distance (export.py draws the
   poster's, hero3d.js re-measures it as the camera moves). Corner: .hs-tl/tc/tr/bl/bc/br. ---- */
.hero-scale { position: absolute; z-index: 2; padding: 6px 11px 7px; border-radius: 10px; background: rgba(36, 38, 42, 0.64); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); color: #fff; pointer-events: none; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12); }
.hs-tl { left: 10px; top: 8px; } .hs-tr { right: 10px; top: 8px; } .hs-tc { left: 50%; top: 8px; transform: translateX(-50%); }
.hs-bl { left: 10px; bottom: 10px; } .hs-br { right: 56px; bottom: 10px; } .hs-bc { left: 50%; bottom: 10px; transform: translateX(-50%); }
.hero:not(.is-3d) .hs-br { right: 12px; bottom: 54px; }   /* above the poster's "Explore in 3D" pill */
.hs-title { display: block; margin: 0 0 5px 2px; font: 700 11px/1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; letter-spacing: 0.09em; text-transform: uppercase; }
.hs-bar { position: relative; height: 28px; margin: 0 16px 0 6px; }
.hs-line { position: absolute; left: 0; right: 0; top: 6px; height: 2px; background: #fff; border-radius: 1px; }
.hs-t { position: absolute; top: 4px; width: 1.5px; height: 6px; margin-left: -0.75px; background: rgba(255, 255, 255, 0.7); }
.hs-t.hs-M { top: 0; width: 2px; height: 14px; margin-left: -1px; background: #fff; }
.hs-n { position: absolute; top: 16px; transform: translateX(-50%); white-space: nowrap; font: 650 13px/1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; font-variant-numeric: tabular-nums; }
.hs-n:first-of-type { transform: translateX(-35%); }
@media (max-width: 640px) { .hero-scale { padding: 7px 10px 8px; } .hs-n { font-size: 12px; } .hs-title { font-size: 11px; } }

/* ---- keyboard: product links, visible only while focused ---- */
.hero-keys { position: absolute; left: 10px; top: 10px; z-index: 5; display: flex; gap: 6px; flex-wrap: wrap; }
.hero-keys a { position: absolute; left: -9999px; background: var(--hero-chip); color: #fff; border-radius: 999px; padding: 6px 12px; font: 600 13px/1 system-ui, sans-serif; text-decoration: none; }
.hero-keys a:focus { position: static; outline: 3px solid var(--hero-accent); outline-offset: 2px; }

/* ---- the intro, at first paint and without three.js: the products drop in one by one (rank 5
   first, #1 last), squash and hop on landing, their shadows grow in under them and the rank
   badges pop up. The inline script in the fragment adds .hero--pre (hidden) before the first
   paint and .hero--play once the plate and atlas are decoded. ---- */
@media (prefers-reduced-motion: no-preference) {
  .hero--pre:not(.hero--play) .hero-layer i, .hero--pre:not(.hero--play) .hero-badge { opacity: 0; }
  .hero--play .hero-pr { animation: hero-drop 0.9s both; animation-delay: calc(var(--d) * 170ms + 80ms); }
  .hero--play .hero-sh { animation: hero-shade 0.9s both; animation-delay: calc(var(--d) * 170ms + 80ms); }
  .hero--play .hero-badge { animation: hero-pop 0.42s both; animation-delay: calc(var(--d) * 170ms + 680ms); }
}
/* the scale card fades in as the last rank badge lands */
.hero--pre:not(.hero--play) .hero-scale { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .hero--play .hero-scale { animation: hero-fade 0.5s both; animation-delay: var(--blink-at, 1.8s); }
}
@keyframes hero-fade { from { opacity: 0; } to { opacity: 1; } }
/* the blinking display (a VCR's 12:00, a TV's input label): the plate shows it lit, and a small
   sprite of the same spot with it off covers it every other BLINK_MS (600 ms, like the 3D viewer),
   from the end of the intro (--blink-at, set per bundle). Reduced motion: it stays lit. */
.hero-bk { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .hero--play .hero-bk { animation: hero-blink 1.2s step-end var(--blink-at, 1.8s) infinite; }
}
@keyframes hero-blink {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}
@keyframes hero-drop {
  0% { opacity: 0; transform: translate3d(0, -24cqw, 0) rotate(var(--tilt, 0deg)) scale(1.06); animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.5); }
  10% { opacity: 1; }
  52% { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg) scale(1, 1); animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1); }
  60% { transform: translate3d(0, 0, 0) scale(1.045, 0.9); animation-timing-function: cubic-bezier(0.3, 0.6, 0.5, 1); }
  75% { transform: translate3d(0, -1.5cqw, 0) scale(0.985, 1.03); animation-timing-function: cubic-bezier(0.5, 0, 0.8, 0.6); }
  86% { transform: translate3d(0, 0, 0) scale(1.015, 0.975); animation-timing-function: ease-out; }
  100% { opacity: 1; transform: none; }
}
/* a high product's shadow is wide, faint and soft; it tightens and darkens as the product lands */
@keyframes hero-shade {
  0%, 22% { opacity: 0; transform: scale(1.3); filter: blur(12px); animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.5); }
  52% { opacity: 1; transform: scale(1); filter: blur(0); }
  75% { opacity: 0.85; transform: scale(1.025); filter: blur(1px); }
  86%, 100% { opacity: 1; transform: none; filter: none; }
}
@keyframes hero-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
  60% { opacity: 1; transform: translate(-50%, -50%) scale(1.18); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-canvas, .hero-hs, .hero-tip, .hero-3d-btn, .hero-zoom-btn { transition: none; }
}

.hero { aspect-ratio: 2400 / 1500; }
.hero:has(.hero-hs[data-id="pilot-g2"]:hover) .hero-tip[data-id="pilot-g2"], .hero:has(.hero-hs[data-id="pilot-g2"]:focus-visible) .hero-tip[data-id="pilot-g2"] { visibility: visible; opacity: 1; transition-delay: 0s; }
.hero:has(.hero-hs[data-id="pentel-energel-rtx"]:hover) .hero-tip[data-id="pentel-energel-rtx"], .hero:has(.hero-hs[data-id="pentel-energel-rtx"]:focus-visible) .hero-tip[data-id="pentel-energel-rtx"] { visibility: visible; opacity: 1; transition-delay: 0s; }
.hero:has(.hero-hs[data-id="uniball-207-ultra-micro"]:hover) .hero-tip[data-id="uniball-207-ultra-micro"], .hero:has(.hero-hs[data-id="uniball-207-ultra-micro"]:focus-visible) .hero-tip[data-id="uniball-207-ultra-micro"] { visibility: visible; opacity: 1; transition-delay: 0s; }
.hero:has(.hero-hs[data-id="zebra-sarasa-clip-vintage"]:hover) .hero-tip[data-id="zebra-sarasa-clip-vintage"], .hero:has(.hero-hs[data-id="zebra-sarasa-clip-vintage"]:focus-visible) .hero-tip[data-id="zebra-sarasa-clip-vintage"] { visibility: visible; opacity: 1; transition-delay: 0s; }
.hero:has(.hero-hs[data-id="paper-mate-inkjoy-gel"]:hover) .hero-tip[data-id="paper-mate-inkjoy-gel"], .hero:has(.hero-hs[data-id="paper-mate-inkjoy-gel"]:focus-visible) .hero-tip[data-id="paper-mate-inkjoy-gel"] { visibility: visible; opacity: 1; transition-delay: 0s; }
.hero-layer[data-variant="phone"], .hero-hotspots[data-variant="phone"], .hero-badges[data-variant="phone"] { display: none; }
@media (max-width: 640px) { .hero { aspect-ratio: 1440 / 1800; } .hero-layer[data-variant="phone"], .hero-hotspots[data-variant="phone"], .hero-badges[data-variant="phone"] { display: block; } .hero-layer[data-variant="wide"], .hero-hotspots[data-variant="wide"], .hero-badges[data-variant="wide"] { display: none; } }
