/* ============================================================
   A7mad.me · Components
   Pixel signature: crisp borders, hard offset shadows, corner
   notches. No game HUD, no vendor logos, no fake data.
   ============================================================ */

/* ---- Scroll progress bar ---- */
.progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 0%;
  z-index: var(--z-progress);
  background: linear-gradient(90deg, var(--accent-warm), var(--brand-primary));
}

/* ---- Intro overlay: Ahmed Tech walk-greet (D-024) ----
   Same cream world as the page so the hand-off feels continuous. */
.intro {
  position: fixed;
  inset: 0;
  z-index: var(--z-intro);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(120% 120% at 50% 40%, var(--surface-primary) 0%, var(--bg-page) 62%);
  overflow: hidden;
}

/* Done: the whole intro lifts up and reveals the hero underneath */
.intro.done {
  animation: introLift 0.65s var(--ease-soft) forwards;
}

.intro[hidden] {
  display: none;
}

@keyframes introLift {
  0% { transform: translateY(0); opacity: 1; }
  100% { transform: translateY(-100%); opacity: 0.6; visibility: hidden; }
}

.intro__wordmark {
  position: absolute;
  top: clamp(28px, 7vh, 64px);
  font-size: clamp(28px, 5vw, 40px);
  color: var(--text-primary);
  opacity: 0.85;
}

.intro__stage {
  position: relative;
  width: min(90vw, 640px);
  height: 300px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.intro__ground {
  position: absolute;
  bottom: 38px;
  inset-inline: 0;
  height: 2px;
  background: repeating-linear-gradient(
    90deg,
    var(--border-soft) 0 14px,
    transparent 14px 24px
  );
}

/* Walker: state machine drives transform via classes (JS).
   RTL: enters from the inline-start edge (right) and walks toward center. */
.intro__walker {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  margin-bottom: 40px;
  transform: translateX(min(46vw, 300px));
  opacity: 0;
}

.intro__walker.is-walking {
  opacity: 1;
  transition: transform 1.5s var(--ease-soft), opacity 0.3s ease;
  transform: translateX(0);
}

/* keeps the walker in place after the walk class is swapped out */
.intro__walker.is-arrived {
  opacity: 1;
  transform: translateX(0);
}

/* pixel step bob: placeholder only - real frames carry their own motion */
.intro__walker.is-walking .char-sprite--intro:not(.has-sprite) {
  animation: walkBob 0.32s steps(2) infinite;
}

@keyframes walkBob {
  0% { transform: translateY(0); }
  100% { transform: translateY(-3px); }
}

.intro__walker.is-settling .char-sprite--intro:not(.has-sprite) {
  animation: settleDip 0.3s var(--ease-out) 1;
}

@keyframes settleDip {
  0% { transform: translateY(-3px); }
  55% { transform: translateY(1px); }
  100% { transform: translateY(0); }
}

/* greet: tiny lean = placeholder wave until the sprite lands */
.intro__walker.is-greeting .char-sprite--intro:not(.has-sprite) {
  animation: greetLean 0.6s var(--ease-out) 1;
}

@keyframes greetLean {
  0%, 100% { transform: rotate(0); }
  40% { transform: rotate(-3deg); }
}

/* D-045: anchored just above the character's head (the charbox is
   taller than the sprite), tail side toward the waving hand.
   Growth expands up/out and never pushes the character. */
.intro__charbox .bubble--intro {
  position: absolute;
  /* bottom is set precisely by JS from the real character height */
  bottom: 60%;
  left: 50%;
  transform: translateX(-112%) translateY(8px);
  width: max-content;
  max-width: min(60vw, 300px);
  min-width: 74px;
  opacity: 0;
  transition: opacity 0.3s var(--ease-out);
}

/* single flowing line inside the intro bubble */
.intro__charbox .bubble--intro .seg {
  display: inline;
}

.intro__walker.is-greeting .intro__charbox .bubble--intro:not([hidden]),
.intro__walker.is-done .intro__charbox .bubble--intro:not([hidden]) {
  opacity: 1;
  transform: translateX(-112%);
}

/* Fixed viewport: owns layout space; the sprite inside is sized and
   swapped by JS without ever moving the stage (D-024 v2). */
.intro__charbox {
  position: relative;
  width: clamp(120px, 26vw, 170px);
  height: clamp(250px, 52vw, 340px);
}

/* the intro bubble anchors to the charbox top */
.intro__charbox .bubble--intro {
  z-index: 2;
}

.char-sprite--intro {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  /* width/height set per sheet by JS to keep the apparent character
     height identical across walk / stop-raise / wave */
}

.intro__skip {
  position: absolute;
  bottom: 28px;
  inset-inline-start: 28px;
  padding: 10px 22px;
  background: none;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-btn);
  color: var(--text-muted);
  font-family: var(--font-ar);
  font-size: var(--fs-small);
  cursor: pointer;
  transition: color var(--t-fast), border-color var(--t-fast);
}

.intro__skip:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
}

/* ============================================================
   Sprite sheets (D-023/D-048): JS engines (breathing loops +
   intro) mount a sheet by adding .has-sprite and setting the
   --sprite-* vars. Without a mounted sheet the element keeps its
   neutral slot look (never a broken image).
   ============================================================ */
/* Grid sprite sheets: JS players set --sprite-x / --sprite-y per frame.
   pixelated keeps the pixel-art edges crisp; frames never resize.
   backface-visibility promotes a stable compositor layer so mobile
   scrolling can't flash/drop the sprite while repainting (D-047). */
.char-sprite {
  image-rendering: pixelated;
  backface-visibility: hidden;
}

.char-slot--img img {
  backface-visibility: hidden;
  transform: translateZ(0);
}

.char-slot.char-sprite.has-sprite,
.char-sprite.has-sprite {
  border: 0;
  background-color: transparent;
  background-image: var(--sprite-src);
  background-repeat: no-repeat;
  background-size: calc(var(--sprite-cols) * 100%) calc(var(--sprite-rows) * 100%);
  background-position: var(--sprite-x, 0%) var(--sprite-y, 0%);
}

.char-sprite.has-sprite .char-slot__mark,
.char-sprite.has-sprite .char-sprite__mark {
  display: none;
}

/* Real static art replaces the neutral slot chrome entirely.
   Doubled class beats the base .char-slot rule that is declared
   later in this file (same specificity would lose by order). */
.char-slot.char-slot--img {
  border: 0;
  background: none;
}

.char-slot.char-slot--img::after {
  display: none;
}

.char-slot.char-slot--img img {
  display: block;
  width: 100%;
  height: auto;
  image-rendering: pixelated;
}

.char-slot--masar {
  width: clamp(110px, 30%, 150px);
  aspect-ratio: auto;
  flex: none;
}

.char-slot--homewatch {
  width: clamp(96px, 26%, 130px);
  aspect-ratio: auto;
  flex: none;
}

/* The intro placeholder frame reuses the neutral slot look */
.char-sprite--intro {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--border-soft);
  border-radius: var(--r-card);
  background:
    radial-gradient(circle at 50% 80%, var(--glow-warm), transparent 72%),
    var(--surface-primary);
}

.char-sprite__mark {
  font-size: 15px;
  color: var(--border-soft);
  letter-spacing: 0.14em;
  writing-mode: vertical-lr;
}

/* ---- Nav ---- */
.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: var(--bg-page);
  border-bottom: 1px solid var(--border-soft);
  transition: box-shadow 0.35s ease;
}

.nav__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: 16px var(--side-pad);
  display: flex;
  align-items: center;
  gap: 28px;
  transition: padding 0.35s ease;
}

.nav[data-scrolled] {
  box-shadow: var(--shadow-soft);
}

.nav[data-scrolled] .nav__inner {
  padding-block: 9px;
}

.nav__brand {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Brand mark slot (D-030): geometric placeholder until the real
   character-head-mark lands. Same box the final head will fill. */
.brand-mark {
  width: 38px;
  height: 38px;
  flex: none;
  background: var(--brand-primary);
  clip-path: var(--chamfer-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  image-rendering: pixelated;
  transition: transform 0.35s ease;
}

.nav[data-scrolled] .brand-mark {
  transform: scale(0.88);
}

.nav__brand:hover .brand-mark {
  transform: translateY(-2px);
}

.brand-mark i {
  width: 13px;
  height: 13px;
  background: var(--bg-page);
  box-shadow: -4px 4px 0 var(--accent-warm);
  transform: translate(2px, -2px);
}

/* Real head mark: high-res source scales down smoothly at 38px */
.brand-mark--img {
  background: none;
  clip-path: none;
}

.brand-mark--img img {
  display: block;
  width: 38px;
  height: 38px;
  image-rendering: auto;
}

/* Mobile menu button: hidden on desktop */
.nav__menu-btn {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 44px;
  height: 44px;
  padding: 10px;
  margin-inline-start: auto;
  background: none;
  border: 1px solid var(--border-soft);
  clip-path: var(--chamfer-sm);
  cursor: pointer;
}

.nav__menu-btn i {
  display: block;
  height: 2px;
  background: var(--text-primary);
  transition: transform 0.25s var(--ease-out), opacity 0.2s;
}

.nav__menu-btn[aria-expanded="true"] i:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.nav__menu-btn[aria-expanded="true"] i:nth-child(2) {
  opacity: 0;
}

.nav__menu-btn[aria-expanded="true"] i:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.nav__brand > .px-label {
  font-size: 24px;
  color: var(--text-primary);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 28px;
  margin-inline-start: auto;
  font-size: 15px;
  color: var(--text-muted);
}

.nav__link {
  position: relative;
  padding-block: 4px;
  transition: color var(--t-fast);
}

.nav__link::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 2px;
  background: var(--accent-warm);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform var(--t-fast) var(--ease-out);
}

.nav__link:hover,
.nav__link[aria-current] {
  color: var(--brand-primary);
}

.nav__link:hover::after,
.nav__link[aria-current]::after {
  transform: scaleX(1);
}

/* ---- Buttons: chamfered pixel corners, navy-family depth (D-036) ---- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-family: var(--font-ar);
  font-weight: 700;
  font-size: 16px;
  padding: 14px 28px;
  min-height: 48px; /* touch target */
  border: 0;
  clip-path: var(--chamfer-sm);
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease-out), filter var(--t-fast) var(--ease-out), background var(--t-fast), color var(--t-fast);
}

.btn--primary {
  background: var(--brand-primary);
  color: var(--bg-page);
  filter: drop-shadow(-3px 4px 0 var(--brand-deep));
}

.btn--primary:hover {
  transform: translate(1px, -2px);
  filter: drop-shadow(-4px 6px 0 var(--brand-deep)) drop-shadow(0 0 7px var(--glow-brand));
}

.btn--primary:active {
  transform: translate(-1px, 2px);
  filter: drop-shadow(-1px 1px 0 var(--brand-deep));
}

/* Secondary: light surface, navy text, quiet warm accent border */
.btn--ghost {
  background: var(--accent-warm);
  color: var(--text-primary);
  padding: 0;
}

.btn--ghost .btn__inner {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 46px;
  margin: 1px;
  padding: 13px 27px;
  background: var(--surface-primary);
  clip-path: var(--chamfer-sm);
}

.btn--ghost:hover {
  transform: translateY(-2px);
  filter: drop-shadow(0 3px 0 var(--glow-brand));
}

.btn--sm {
  padding: 10px 20px;
  min-height: 42px;
  font-size: 14.5px;
}

/* ---- Marquee ---- */
.marquee {
  border-block: 1px solid var(--border-soft);
  background: linear-gradient(90deg, var(--glow-warm-faint), transparent 40%, var(--glow-warm-faint));
  overflow: hidden;
  padding-block: 16px;
}

.marquee__track {
  display: flex;
  width: max-content;
  animation: marqueeMove 42s linear infinite;
}

.marquee__seq {
  display: flex;
  align-items: center;
  gap: 44px;
  padding-inline-end: 44px;
  font-size: 17px;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
}

.marquee__seq i {
  width: 7px;
  height: 7px;
  background: var(--beige);
  flex: none;
}

@keyframes marqueeMove {
  /* RTL page: translate toward +X so the strip drifts naturally */
  0% { transform: translateX(0); }
  100% { transform: translateX(50%); }
}

/* ---- Speech bubble: Ahmed Tech brand element (D-035) ----
   Navy shell + cream surface, chamfered pixel corners and a pixel
   tail carved from one clip-path. Dual layer = shell paints the
   2px navy border, ::before paints the surface. */
.bubble {
  position: relative;
  max-width: 34ch;
  background: var(--border-strong);
  clip-path: var(--bubble-clip);
  padding: 15px 20px 29px; /* bottom includes the 12px tail strip + 2px rim */
  font-size: 16px;
  line-height: 1.75;
  color: var(--text-primary);
  filter: drop-shadow(-2px 3px 0 var(--glow-brand));
}

.bubble::before {
  content: '';
  position: absolute;
  inset: 2px;
  background:
    linear-gradient(180deg, var(--surface-raised) 0%, var(--surface-primary) 26%);
  clip-path: var(--bubble-clip);
  z-index: 0;
}

.bubble > * {
  position: relative;
  z-index: 1;
}

.bubble .seg {
  display: block;
}

.bubble .seg + .seg {
  margin-top: 4px;
}

/* ---- Character slot (reserved, no fake character) ---- */
.char-slot {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--border-soft);
  border-radius: var(--r-card);
  background:
    radial-gradient(circle at 50% 80%, var(--glow-warm), transparent 72%),
    var(--surface-primary);
}

.char-slot__mark {
  font-size: 17px;
  color: var(--border-soft);
  letter-spacing: 0.14em;
  writing-mode: vertical-lr;
}

.char-slot::after {
  content: '';
  position: absolute;
  bottom: 12px;
  width: 58%;
  height: 10px;
  background: var(--glow-brand);
  border-radius: 50%;
  filter: blur(4px);
}

.stage__row {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 18px;
  width: 100%;
  flex-wrap: wrap;
}

/* Breathing-loop characters (D-048, amended 08-24) - hero + Baqati.
   Responsibilities split hard:
   .char-slot--*   = stable FRAME: owns width/height/layout only.
   .char-viewport  = fixed crop window: overflow hidden, nothing else.
   .*-sprite       = breathing-loop playback only: sheet + frame
   position. One persistent layer per character whose
   background-image never changes at runtime, so nothing can
   flash mid-scroll. */
.char-slot--hero {
  width: min(58%, 200px);
  aspect-ratio: 2 / 3;
}

.char-viewport {
  position: absolute;
  inset: 0;
  overflow: hidden;
  transform: translateZ(0); /* own compositor layer: scroll repaints
                               can't drop the sprite (D-048) */
}

.hero-sprite,
.baqati-sprite {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%) translateZ(0);
}

/* engine mounted: the neutral slot chrome retires */
.char-slot.is-live {
  border: 0;
  background: none;
}

.char-slot.is-live .char-slot__mark,
.char-slot.is-live::after {
  display: none;
}
.char-slot--stage { width: clamp(88px, 24%, 118px); aspect-ratio: 10 / 13; flex: none; }
.char-slot--sm { width: clamp(78px, 20%, 96px); }
.char-slot--project { width: min(52%, 180px); aspect-ratio: 10 / 13; }
.char-slot--inline { width: 150px; aspect-ratio: 10 / 13; flex: none; }

/* ---- Project pieces ---- */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  font-size: 13.5px;
  font-weight: 500;
  border-radius: var(--r-btn);
  border: 1px solid var(--border-soft);
  background: var(--bg-page);
  color: var(--text-secondary);
}

.tag--live {
  border-color: var(--accent-warm);
  color: var(--accent-warm);
}

.tag--live i {
  width: 7px;
  height: 7px;
  background: var(--accent-warm);
  animation: livePulse 2.6s ease-in-out infinite;
}

@keyframes livePulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.tag--wip {
  border-color: var(--text-secondary);
  color: var(--text-secondary);
  background: var(--surface-warm);
}

.chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 13px;
  font-size: 13.5px;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-btn);
  background: var(--bg-page);
  color: var(--text-secondary);
  transition: border-color var(--t-fast), transform var(--t-fast);
}

.chip:hover {
  border-color: var(--accent-warm);
  transform: translateY(-1px);
}

.stage__link {
  font-weight: 700;
  color: var(--accent-warm);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: transform var(--t-fast) var(--ease-out);
}

.stage__link:hover {
  transform: translateX(-3px);
}

/* Stage hover life: slight lift, glow deepens a touch - never neon */
.stage {
  transition: filter var(--t-med), transform var(--t-med) var(--ease-out);
}

.stage:hover {
  transform: translateY(-2px);
  filter:
    drop-shadow(0 16px 24px rgba(28, 47, 73, 0.15))
    drop-shadow(0 0 22px rgba(36, 58, 90, 0.13));
}

.stage__scene,
.laptop {
  transition: transform 0.4s var(--ease-out);
}

.stage:hover .stage__scene {
  transform: translateY(-5px);
}

/* ---- Laptop frame (Baqati) - real screenshot drops into .laptop__screen ---- */
.laptop {
  width: min(100%, 290px);
  position: relative;
}

.laptop__lid {
  border: 2px solid var(--border-strong);
  border-radius: var(--r-card);
  background: var(--brand-primary);
  padding: 10px 10px 14px;
  box-shadow: -4px 6px 0 var(--glow-brand);
}

.laptop__screen {
  aspect-ratio: 16 / 10;
  background:
    linear-gradient(150deg, var(--surface-warm), var(--surface-primary) 70%);
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 8px;
}

.laptop__screen .px-label {
  font-size: 22px;
  color: var(--text-muted);
  text-transform: none;
}

.laptop__screen small {
  font-size: 12px;
  color: var(--text-muted);
}

.laptop__base {
  height: 10px;
  margin-inline: -8px;
  background: var(--text-secondary);
  border: 2px solid var(--border-strong);
  border-top: 0;
  border-radius: 0 0 6px 6px;
}

/* ---- Masar pixel concept scene (decor only, clearly not a screenshot) ---- */
.pixel-scene {
  width: min(100%, 290px);
  aspect-ratio: 16 / 10;
  position: relative;
  border: 2px solid var(--border-strong);
  border-radius: var(--r-card);
  background: linear-gradient(180deg, var(--surface-primary) 55%, var(--surface-warm) 55%);
  overflow: hidden;
  box-shadow: -4px 6px 0 var(--glow-brand);
}

.pixel-scene i {
  position: absolute;
  background: var(--beige);
}

.pixel-scene i:nth-child(1) { width: 34px; height: 34px; bottom: 18%; inset-inline-start: 12%; background: var(--accent-warm); }
.pixel-scene i:nth-child(2) { width: 22px; height: 52px; bottom: 18%; inset-inline-start: 34%; background: var(--text-secondary); }
.pixel-scene i:nth-child(3) { width: 46px; height: 22px; bottom: 18%; inset-inline-end: 16%; }
.pixel-scene i:nth-child(4) { width: 12px; height: 12px; top: 20%; inset-inline-start: 22%; }
.pixel-scene i:nth-child(5) { width: 8px; height: 8px; top: 32%; inset-inline-end: 28%; background: var(--accent-warm); }

.pixel-scene figcaption {
  position: absolute;
  top: 10px;
  inset-inline-end: 10px;
  font-size: 12px;
  color: var(--text-muted);
  background: var(--bg-page);
  border: 1px solid var(--border-soft);
  padding: 2px 9px;
  border-radius: var(--r-btn);
}

/* ---- HomeWatch photo slot ---- */
.photo-slot {
  width: min(100%, 290px);
  aspect-ratio: 4 / 3;
  border: 2px dashed var(--border-soft);
  border-radius: var(--r-card);
  background:
    radial-gradient(circle at 50% 50%, var(--glow-warm-faint), transparent 70%),
    var(--surface-primary);
  display: flex;
  align-items: center;
  justify-content: center;
}

.photo-slot span {
  font-size: 13px;
  color: var(--text-muted);
}

/* ---- Cycler dots ---- */
.dots {
  display: flex;
  align-items: center;
  gap: 9px;
}

.dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  background: var(--beige);
  cursor: pointer;
  transition: width 0.35s var(--ease-out), background 0.35s;
}

.dot.on {
  width: 30px;
  background: var(--accent-warm);
}

/* ---- Skills AI bubble block ---- */
.ai-note {
  display: flex;
  align-items: flex-end;
  gap: 24px;
}

/* ---- Divider (pixel signature) ---- */
.px-divider {
  display: flex;
  justify-content: center;
  gap: 8px;
  padding-block: 6px;
}

.px-divider i {
  width: 8px;
  height: 8px;
  background: var(--beige);
}

.px-divider i:nth-child(2) { background: var(--accent-warm); }

/* ============================================================
   Baqati live scene (D-026): hierarchical motion.
   Core (laptop) still; only secondary details breathe.
   --project-glow stays Ahmed Tech until a real asset proves
   the project color (D-020).
   ============================================================ */
.stage--baqati .stage__visual {
  position: relative;
}

.scene-glow {
  position: absolute;
  inset: 10%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--project-glow), transparent 68%);
  filter: blur(6px);
  animation: sceneBreathe 9s ease-in-out infinite;
  pointer-events: none;
}

@keyframes sceneBreathe {
  0%, 100% { opacity: 0.7; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.05); }
}

/* Abstract UI planes: plain layered surfaces, no fake content */
.ui-plane {
  position: absolute;
  border: 1px solid var(--border-soft);
  background: var(--surface-primary);
  border-radius: var(--r-card);
  box-shadow: -2px 3px 0 var(--glow-brand);
  pointer-events: none;
  transition: transform 0.45s var(--ease-out);
}

.ui-plane--a {
  width: 64px;
  height: 44px;
  top: 38%;
  inset-inline-start: 7%;
  animation: planeFloatA 11s ease-in-out infinite;
}

.ui-plane--b {
  width: 46px;
  height: 32px;
  bottom: 18%;
  inset-inline-end: 10%;
  animation: planeFloatB 14s ease-in-out infinite;
}

@keyframes planeFloatA {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}

@keyframes planeFloatB {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(6px); }
}

/* Screen light: one slow sheen, the screen itself stays still */
.laptop__screen {
  position: relative;
  overflow: hidden;
}

.laptop__screen::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 36%;
  background: linear-gradient(100deg, transparent, rgba(253, 252, 249, 0.55), transparent);
  animation: screenSheen 8s cubic-bezier(0.4, 0, 0.3, 1) 2s infinite;
  pointer-events: none;
}

@keyframes screenSheen {
  0% { transform: translateX(220%) skewX(-14deg); }
  45%, 100% { transform: translateX(-320%) skewX(-14deg); }
}

/* Hover depth: planes shift a touch; the laptop only lifts with the
   shared .stage__scene lift. Nothing else moves. */
.stage--baqati:hover .ui-plane--a { transform: translate(4px, -4px); animation-play-state: paused; }
.stage--baqati:hover .ui-plane--b { transform: translate(-4px, 3px); animation-play-state: paused; }

/* ============================================================
   Path motif (D-027): quiet pixel route between stations.
   Straight, never over text, two placements only.
   ============================================================ */
.path-motif {
  position: relative;
  max-width: min(560px, 72vw);
  height: 34px;
  margin: 0 auto;
}

/* the road */
.path-motif::before {
  content: '';
  position: absolute;
  top: 50%;
  inset-inline: 0;
  height: 2px;
  background: repeating-linear-gradient(
    90deg,
    var(--border-soft) 0 12px,
    transparent 12px 20px
  );
}

.path-motif__station {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 10px;
  background: var(--accent-warm);
  inset-inline-start: 0;
}

.path-motif__station--mid {
  inset-inline-start: calc(50% - 5px);
  background: var(--beige);
}

.path-motif__station--end {
  inset-inline-start: auto;
  inset-inline-end: 0;
  background: var(--brand-primary);
}

.path-motif__stone {
  position: absolute;
  width: 5px;
  height: 5px;
  background: var(--beige);
}

.path-motif__stone--a { top: 30%; inset-inline-start: 22%; }
.path-motif__stone--b { top: 62%; inset-inline-start: 38%; }
.path-motif__stone--c { top: 34%; inset-inline-end: 24%; }

.path-motif--journey {
  max-width: 220px;
  margin: 0 0 clamp(28px, 5vw, 40px);
}

/* Live scene freezes while off-screen (perf) */
.stage--baqati.is-offscreen .scene-glow,
.stage--baqati.is-offscreen .ui-plane,
.stage--baqati.is-offscreen .laptop__screen::after {
  animation-play-state: paused;
}

/* ============================================================
   Speech system (D-033/D-034): typewriter for Ahmed's lines only.
   .speech holds a hidden ghost bubble (full text) that reserves
   the FINAL size, so the live bubble can grow inside it without
   any layout shift. Without JS the ghost simply stays visible.
   ============================================================ */
.speech {
  position: relative;
  width: fit-content;
  max-width: 100%;
}

.speech .bubble--ghost {
  visibility: visible;
}

.speech .bubble--live {
  display: none;
}

/* armed by JS: ghost keeps layout, live types over it.
   D-048: the live bubble anchors to the BOTTOM of the reserved
   zone - the tail edge near the character's head never moves and
   growth extends upward only, away from the head. */
.speech--armed .bubble--ghost {
  visibility: hidden;
}

.speech--armed .bubble--live {
  display: block;
  position: absolute;
  bottom: 0;
  inset-inline-start: 0;
  width: fit-content;
  max-width: 100%;
  min-width: 74px;
  min-height: 58px;
  opacity: 0;
  transform: translateY(6px);
}

.speech.is-revealed .bubble--live {
  opacity: 1;
  transform: none;
  transition: opacity 0.28s var(--ease-out), transform 0.28s var(--ease-out);
}

/* birth glow: brief, then settles (no continuous pulse) */
.speech.is-typing .bubble--live {
  filter: drop-shadow(-2px 3px 0 var(--glow-brand)) drop-shadow(0 0 9px var(--glow-brand));
}

.speech.is-done .bubble--live {
  filter: drop-shadow(-2px 3px 0 var(--glow-brand));
  transition: filter 0.6s ease;
}

/* pixel typing indicator: absolutely positioned so it never takes
   inline space - its appearance/removal can't re-wrap the text or
   change the bubble's size (root cause of the end-of-speech snap) */
.bubble__dot {
  position: absolute;
  bottom: 17px;
  inset-inline-end: 9px;
  width: 7px;
  height: 7px;
  background: var(--accent-warm);
  animation: dotStep 0.7s steps(2) infinite;
  z-index: 2;
}

.bubble__dot[hidden] {
  display: none; /* absolute: removing it is layout-inert */
}

@keyframes dotStep {
  0% { opacity: 1; }
  100% { opacity: 0.2; }
}

/* ============================================================
   Baqati scene v2 (D-037): background display panel carries the
   real screenshot; seated Ahmed + angled laptop in front.
   ============================================================ */
.stage__scene--baqati {
  gap: 14px;
}

.display-panel {
  width: min(100%, 330px);
  background: var(--border-mid);
  padding: 1px;
  clip-path: var(--chamfer-md);
  filter: drop-shadow(0 8px 16px rgba(28, 47, 73, 0.12));
}

.display-panel__screen {
  aspect-ratio: 16 / 10;
  background:
    radial-gradient(circle at 50% 30%, var(--glow-warm-faint), transparent 70%),
    linear-gradient(165deg, var(--surface-raised), var(--surface-warm) 90%);
  clip-path: var(--chamfer-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.display-panel__screen .px-label {
  font-size: 22px;
  color: var(--text-muted);
  text-transform: none;
}

.display-panel__screen small {
  font-size: 12px;
  color: var(--text-muted);
}

/* desk row overlaps the panel so Ahmed reads as the focal point */
.baqati-desk {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 10px;
  margin-top: -34px;
  position: relative;
  z-index: 1;
}

.char-slot--seated {
  /* D-049 + Ahmed 08-24: one step smaller again */
  width: clamp(115px, 33%, 155px);
  aspect-ratio: 3 / 4;
  flex: none;
}

.laptop--angled {
  width: 150px;
  flex: none;
  transform: rotate(-5deg) translateY(-4px);
  transform-origin: bottom center;
}

/* ============================================================
   Mobile navigation panel (D-038)
   ============================================================ */
.nav__links.is-open {
  display: flex;
}
