/* ==========================================================================
   DEVICE MOCKUP SYSTEM
   Reusable HTML/CSS frames for desktop monitors, browser windows, tablets
   and phones, plus the screenshot strip that drives them.

   A project declares what it genuinely supports in markup only:

     <div class="device-stage" data-device-stage data-project="cenro"
          data-device-label="CENRO device previews"
          data-mobile-default="phone" data-composition="overlap">
       <figure class="device-shot" data-device="desktop"> ... </figure>
       <figure class="device-shot" data-device="phone">   ... </figure>
     </div>
     <div class="device-thumbs" role="group" aria-label="...">
       <button class="device-thumb" data-device="desktop" data-shot-target="gallery-cenro-1"
               data-src="..." data-alt="..." aria-pressed="true"> ... </button>
     </div>

   Two rules keep the presentation honest:

   1. The screen area is sized by the screenshot itself (width: 100%;
      height: auto), so every capture keeps its true aspect ratio - nothing is
      cropped, stretched or letterboxed, and no device chrome covers interface
      pixels.
   2. Only genuine captures are declared. A device with no verified screenshot
      simply has no .device-shot, so the project cannot advertise it.

   GLightbox caches slide data when it initialises, so the visible screen is a
   button that delegates to a pre-registered hidden anchor rather than a link
   whose href is rewritten at runtime.
   ========================================================================== */

.device-stage {
  position: relative;
  display: block;
  width: 100%;
  min-width: 0;
}

/* Before the controller runs, every shot stays in flow: a JS failure costs the
   switching affordance, never the screenshots themselves. */
.device-stage[data-ready] .device-shot {
  display: none;
}

.device-stage[data-ready][data-active="desktop"] > .device-shot[data-device="desktop"],
.device-stage[data-ready][data-active="tablet"] > .device-shot[data-device="tablet"],
.device-stage[data-ready][data-active="phone"] > .device-shot[data-device="phone"] {
  display: flex;
}

/* ── One shot = frame + caption, both constrained to the device width ── */
.device-shot {
  --shot-width: 100%;
  width: 100%;
  min-width: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.device-shot[data-device="tablet"] {
  --shot-width: min(100%, clamp(320px, 86%, 520px));
}

.device-shot[data-device="phone"] {
  --shot-width: min(100%, clamp(238px, 60%, 318px));
}

.device-shot > .device-link,
.device-shot > .device-caption {
  width: var(--shot-width);
  margin-inline: auto;
}

/* The screen is a button: it opens the gallery instead of navigating, and the
   target it opens is swapped by the thumbnail strip. */
.device-link {
  appearance: none;
  display: block;
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  text-align: center;
  color: inherit;
  text-decoration: none;
  border-radius: 16px;
  cursor: pointer;
}

.device-link:focus-visible {
  outline: 2px solid var(--accent-primary, #f0a500);
  outline-offset: 6px;
}

/* ── Frame shell ── */
.device-frame {
  position: relative;
  display: block;
  width: 100%;
  background: #12141a;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 20px 46px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35);
  transition: box-shadow 0.35s ease, border-color 0.35s ease;
}

.project-card-showcase:hover .device-frame {
  border-color: rgba(240, 165, 0, 0.32);
  box-shadow: 0 24px 58px rgba(0, 0, 0, 0.62), 0 0 32px rgba(240, 165, 0, 0.08);
}

.device-screen {
  position: relative;
  display: block;
  overflow: hidden;
  background: #0a0b0e;
}

/* The capture defines the screen height, so the frame can never distort it. */
.device-screen img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
}

/* ── Desktop monitor ── */
.device-frame--monitor {
  /* Room for the stand that hangs below the bezel. */
  margin-bottom: 34px;
  padding: 9px 9px 0;
  border-radius: 12px;
  background: linear-gradient(180deg, #282b35 0%, #171a22 45%, #0f1116 100%);
}

.device-frame--monitor .device-screen {
  border-radius: 5px;
}

.device-chin {
  display: block;
  position: relative;
  height: 15px;
}

.device-chin::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 6px;
  width: 5px;
  height: 5px;
  margin-left: -2.5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
}

/* Neck plus base drawn as one clipped shape. */
.device-stand {
  position: absolute;
  left: 50%;
  bottom: -34px;
  transform: translateX(-50%);
  width: clamp(84px, 26%, 148px);
  height: 34px;
  background: linear-gradient(180deg, #22262f 0%, #15171e 46%, #0f1116 100%);
  clip-path: polygon(42% 0, 58% 0, 66% 60%, 100% 60%, 100% 100%, 0 100%, 0 60%, 34% 60%);
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.45));
}

/* ── Browser window ──
   For applications that really are opened in a browser. The address field
   shows the deployment host already stated in the caption, never a invented
   URL, and there are no fake navigation controls. */
.device-frame--browser {
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
  background: linear-gradient(180deg, #22262f 0%, #14161c 100%);
}

.device-browser-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 28px;
  padding: 0 10px;
  background: linear-gradient(180deg, #2c303a 0%, #1d2027 100%);
  border-bottom: 1px solid rgba(0, 0, 0, 0.5);
}

.device-browser-dots {
  display: inline-flex;
  flex: 0 0 auto;
  gap: 5px;
}

.device-browser-dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
}

.device-browser-dots i:first-child {
  background: rgba(255, 255, 255, 0.22);
}

.device-browser-address {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex: 1 1 auto;
  height: 18px;
  padding: 0 9px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.38);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 0.64rem;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.62);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.device-browser-address i {
  font-size: 0.55rem;
  color: #34d399;
}

.device-frame--browser .device-screen {
  border-radius: 0;
  background: #0a0b0e;
}

/* ── Tablet ── */
.device-frame--tablet {
  padding: 13px;
  border-radius: 22px;
  background: linear-gradient(160deg, #2b2f39 0%, #14161c 55%, #0d0f14 100%);
}

.device-frame--tablet .device-screen {
  border-radius: 11px;
}

.device-frame--tablet::before {
  content: '';
  position: absolute;
  top: 5px;
  left: 50%;
  width: 5px;
  height: 5px;
  margin-left: -2.5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
}

/* ── Smartphone ── */
.device-frame--phone {
  padding: 8px;
  border-radius: 32px;
  background: linear-gradient(155deg, #383c47 0%, #1a1d25 42%, #0a0c11 100%);
  box-shadow: 0 24px 54px rgba(0, 0, 0, 0.62), inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}

.device-frame--phone .device-screen {
  border-radius: 25px;
}

/* Speaker slit sits inside the bezel, never over the interface. */
.device-frame--phone::before {
  content: '';
  position: absolute;
  top: 3px;
  left: 50%;
  transform: translateX(-50%);
  width: 16%;
  height: 3px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.14);
}

.device-frame--phone::after {
  content: '';
  position: absolute;
  right: -2px;
  top: 24%;
  width: 3px;
  height: 14%;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, #333844, #12141a);
}

/* ── Enlarge affordance (pointer devices only) ── */
.device-zoom {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: rgba(0, 0, 0, 0.48);
  color: #ffffff;
  font-size: 0.8rem;
  font-weight: 600;
  opacity: 0;
  transition: opacity 0.25s ease;
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.device-link:hover .device-zoom,
.device-link:focus-visible .device-zoom {
  opacity: 1;
}

@media (hover: none) {
  .device-zoom {
    display: none;
  }
}

/* ── Caption: states what the frame is showing, without fake chrome ── */
.device-caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-top: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 0.72rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.62);
}

.device-caption > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow-wrap: anywhere;
}

.device-status {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  font-family: Roboto, system-ui, sans-serif;
  font-size: 0.68rem;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.75);
}

.device-status--live {
  color: #34d399;
  border-color: rgba(52, 211, 153, 0.35);
  background: rgba(52, 211, 153, 0.1);
}

.device-status i {
  font-size: 0.45rem;
}

/* ── Device switcher (built by project-devices.js when 2+ devices exist) ── */
.device-switcher {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 14px;
}

/* The controller hides this while an overlapping composition shows every
   device at once; display: flex above would otherwise beat [hidden]. */
.device-switcher[hidden] {
  display: none;
}

.device-switcher-tabs {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.device-tab {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: rgba(255, 255, 255, 0.7);
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 13px;
  min-height: 34px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.22s ease, color 0.22s ease, border-color 0.22s ease;
}

.device-tab:hover {
  color: #ffffff;
  background: rgba(255, 255, 255, 0.07);
}

.device-tab[aria-selected="true"] {
  color: var(--accent-primary, #f0a500);
  background: rgba(240, 165, 0, 0.14);
  border-color: rgba(240, 165, 0, 0.42);
}

.device-tab:focus-visible {
  outline: 2px solid var(--accent-primary, #f0a500);
  outline-offset: 2px;
}

/* ── Screenshot strip ──
   Replaces the old row of text-only pills: each entry shows the actual
   capture, names it, and loads it into the device frame above. */
.device-thumbs {
  /* Room after the last tile that a floating control may occupy; widened by
     the clearance rule further down. */
  --strip-tail: 0px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 14px;
  padding: 2px 2px 8px;
  padding-inline-end: var(--strip-tail);
  min-width: 0;
  /* The strip scrolls inside itself so a long gallery can never widen the
     page on a phone. Tiles keep one fixed width at every count, so the strip
     reads the same whether a project holds three captures or five; the snap
     points line each tile up with the left edge as it is scrolled. */
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: 2px;
  scrollbar-width: thin;
  scrollbar-color: rgba(240, 165, 0, 0.45) transparent;
}

.device-thumbs::-webkit-scrollbar {
  height: 5px;
}

.device-thumbs::-webkit-scrollbar-thumb {
  border-radius: 999px;
  background: rgba(240, 165, 0, 0.4);
}

.device-thumbs::-webkit-scrollbar-track {
  background: transparent;
}

.device-thumb {
  appearance: none;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 104px;
  padding: 6px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.03);
  color: rgba(255, 255, 255, 0.62);
  font-family: inherit;
  /* One step up from the old 0.63rem: the label is the only thing that says
     which capture a tile holds, so it has to survive the fixed tile width. */
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
  cursor: pointer;
  scroll-snap-align: start;
  scroll-snap-stop: normal;
  transition: background 0.22s ease, border-color 0.22s ease, color 0.22s ease;
}

.device-thumb:hover {
  border-color: rgba(240, 165, 0, 0.35);
  background: rgba(255, 255, 255, 0.06);
  color: #ffffff;
}

.device-thumb[aria-pressed="true"] {
  border-color: rgba(240, 165, 0, 0.6);
  background: rgba(240, 165, 0, 0.1);
  color: #ffffff;
  box-shadow: 0 0 0 1px rgba(240, 165, 0, 0.35), 0 6px 16px rgba(0, 0, 0, 0.35);
}

.device-thumb:focus-visible {
  outline: 2px solid var(--accent-primary, #f0a500);
  outline-offset: 2px;
}

/* contain, never cover: a thumbnail may be small but must not lie about the
   capture it stands for. */
.device-thumb img {
  display: block;
  height: 54px;
  width: auto;
  /* Never wider than the tile that holds it, so a shrunk tap target on a phone
     cannot spill over its own border. */
  max-width: min(92px, 100%);
  object-fit: contain;
  border-radius: 3px;
  background: #0a0b0e;
}

/* Two lines, then an ellipsis: a label may wrap, but it may not push three
   words into a six-line tower that makes one tile taller than its neighbours. */
.device-thumb-label {
  max-width: 100%;
  overflow: hidden;
  overflow-wrap: break-word;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-clamp: 2;
}

/* Which device a thumbnail drives is announced to assistive tech by the
   controller (project-devices.js) rather than drawn on the card, because a
   glyph in the corner would sit over the capture it stands for. */

/* ── Clearance for the floating Back to Top button ──
   The button is a fixed 44px square 24px in from the viewport edge, so it
   reaches 68px into the layout and can sit over the end of a strip that runs
   out to the container edge. Reserving scroll room after the last tile lets
   that tile be brought fully clear of it; scroll-margin makes scrollIntoView
   use the reserved room instead of stopping with the tile under the button.
   The reserve lives inside the strip's own scroller, so it adds scroll range
   and never page width. Above 1400px the centred 1140px container ends well
   clear of the button, so no room is spent there. */
@media (max-width: 1399.98px) {
  .device-thumbs {
    --strip-tail: 64px;
  }

  .device-thumb {
    scroll-margin-inline-end: var(--strip-tail);
  }
}

/* ── Overlapping composition (large screens only) ──
   Used when a project has genuine captures for two devices. The secondary
   device sits beside the primary and reaches only into its bezel, so no
   interface pixels are ever covered. */
@media (min-width: 1200px) {
  .device-stage[data-composition] {
    /* One number for both halves, so the overlap is always the bezel and never
       a moving percentage. */
    --composition-secondary: clamp(148px, 24%, 168px);
  }

  /* Composition is the one case where the single-device hiding rule is lifted:
     every genuine capture is on view at once, which is also why the switcher
     stands down. Written with the [data-ready] guard so the pre-JS layout,
     where all shots are already in flow, is left alone. */
  .device-stage[data-composition][data-ready] > .device-shot {
    display: flex;
  }

  .device-stage[data-composition] > .device-shot[data-device="desktop"] {
    /* The phone's frame reaches exactly over the monitor's 10px bezel, so the
       two read as one composition without the secondary device ever covering
       interface pixels on the primary screen. */
    width: calc(100% - var(--composition-secondary) + 10px);
    align-items: stretch;
  }

  .device-stage[data-composition] > .device-shot[data-device="desktop"] > .device-link {
    width: 100%;
  }

  /* The caption stops short of the bezel the phone sits on - the 10px the phone
     bites plus the shot's own centring - so its status pill is never hidden
     behind the secondary device. */
  .device-stage[data-composition] > .device-shot[data-device="desktop"] > .device-caption {
    width: calc(100% - 24px);
  }

  /* The percentage resolves against the stage, so the shot gets an explicit
     width instead of a shrink-to-fit one its children cannot measure. */
  .device-stage[data-composition] > .device-shot[data-device="phone"] {
    width: var(--composition-secondary);
    position: absolute;
    top: 4px;
    right: 0;
    z-index: 2;
  }

  .device-stage[data-composition] > .device-shot[data-device="phone"] > .device-link,
  .device-stage[data-composition] > .device-shot[data-device="phone"] > .device-caption {
    width: 100%;
  }

  .device-stage[data-composition] > .device-shot[data-device="phone"] .device-frame--phone {
    box-shadow: 0 26px 52px rgba(0, 0, 0, 0.7),
      inset 0 0 0 1px rgba(255, 255, 255, 0.08),
      0 0 26px rgba(240, 165, 0, 0.12);
  }

  /* The strip already names every capture; a second caption under a
     150px-wide phone would only add clutter. */
  .device-stage[data-composition] > .device-shot[data-device="phone"] .device-caption {
    display: none;
  }

  .device-stage[data-composition] ~ .device-switcher {
    display: none;
  }
}

/* ── Light theme ── */
html[data-theme="light"] .device-frame--monitor {
  background: linear-gradient(180deg, #f4f6fa 0%, #d9dde6 55%, #c7ccd7 100%);
  border-color: rgba(0, 0, 0, 0.14);
}

html[data-theme="light"] .device-frame--browser {
  background: linear-gradient(180deg, #eef1f6 0%, #dfe3ea 100%);
  border-color: rgba(0, 0, 0, 0.14);
}

html[data-theme="light"] .device-browser-bar {
  background: linear-gradient(180deg, #e6eaf1 0%, #d3d8e2 100%);
  border-bottom-color: rgba(0, 0, 0, 0.12);
}

html[data-theme="light"] .device-browser-dots i {
  background: rgba(0, 0, 0, 0.18);
}

html[data-theme="light"] .device-browser-dots i:first-child {
  background: rgba(0, 0, 0, 0.26);
}

html[data-theme="light"] .device-browser-address {
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
  color: #475569;
}

html[data-theme="light"] .device-frame--tablet {
  background: linear-gradient(160deg, #eef1f6 0%, #d0d5df 60%, #bcc2cd 100%);
  border-color: rgba(0, 0, 0, 0.14);
}

html[data-theme="light"] .device-frame--phone {
  background: linear-gradient(155deg, #eceff4 0%, #c8cdd8 45%, #aab0bc 100%);
  border-color: rgba(0, 0, 0, 0.16);
}

html[data-theme="light"] .device-stand {
  background: linear-gradient(180deg, #d5d9e2 0%, #b6bcc7 100%);
}

html[data-theme="light"] .device-chin::after,
html[data-theme="light"] .device-frame--tablet::before,
html[data-theme="light"] .device-frame--phone::before {
  background: rgba(0, 0, 0, 0.22);
}

html[data-theme="light"] .device-frame--phone::after {
  background: linear-gradient(180deg, #c2c7d2, #9aa1ad);
}

html[data-theme="light"] .device-screen {
  background: #eef2f7;
}

html[data-theme="light"] .device-caption {
  color: #64748b;
}

html[data-theme="light"] .device-status {
  border-color: rgba(0, 0, 0, 0.12);
  color: #475569;
}

html[data-theme="light"] .device-status--live {
  color: #047857;
  border-color: rgba(4, 120, 87, 0.3);
  background: rgba(4, 120, 87, 0.08);
}

html[data-theme="light"] .device-switcher-tabs {
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.1);
}

html[data-theme="light"] .device-tab {
  color: #475569;
}

html[data-theme="light"] .device-tab:hover {
  color: #0f172a;
  background: rgba(0, 0, 0, 0.05);
}

html[data-theme="light"] .device-tab[aria-selected="true"] {
  color: #b45309;
  background: rgba(217, 119, 6, 0.12);
  border-color: rgba(217, 119, 6, 0.4);
}

html[data-theme="light"] .device-thumb {
  border-color: rgba(0, 0, 0, 0.1);
  background: rgba(0, 0, 0, 0.03);
  color: #475569;
}

html[data-theme="light"] .device-thumb:hover {
  border-color: rgba(217, 119, 6, 0.4);
  background: rgba(0, 0, 0, 0.06);
  color: #0f172a;
}

html[data-theme="light"] .device-thumb[aria-pressed="true"] {
  border-color: rgba(217, 119, 6, 0.6);
  background: rgba(217, 119, 6, 0.09);
  color: #0f172a;
  box-shadow: 0 0 0 1px rgba(217, 119, 6, 0.32);
}

html[data-theme="light"] .device-thumb img {
  background: #e6ebf3;
}

/* ── Tablet: phone preview cap in single-column layout ──
   Between 576px and 991px the card is one column, so a portrait phone frame
   has the full card width to grow into. Without a cap the KaSpot phone mockup
   stands taller than the section above it and pushes the body well off screen.
   The cap leaves the phone narrow enough to feel like a phone and keeps the
   strip visible below it without scrolling. */
@media (min-width: 576px) and (max-width: 991px) {
  .device-shot[data-device="phone"] {
    --shot-width: min(100%, clamp(240px, 46%, 320px));
  }
}

/* ── Narrow screens: full-width controls, larger tap targets ── */
@media (max-width: 575.98px) {
  /* A phone mockup is portrait, so it is the one frame whose height runs away
     with the card: at its old 208-286px it stood taller than the phone it
     depicts and pushed the rest of the project off screen. The cap is a share
     of the column and a share of the viewport height, whichever is smaller,
     so a short 320x568 screen does not get a 460px mockup. The capture keeps
     its own ratio - only the frame width changes. */
  .device-shot[data-device="phone"] {
    --shot-width: min(100%, 252px, max(184px, 52%), calc(0.26 * 100svh));
  }

  .device-frame--phone {
    padding: 7px;
    border-radius: 28px;
  }

  .device-frame--phone .device-screen {
    border-radius: 22px;
  }

  .device-caption {
    margin-top: 9px;
  }

  /* The caption describes the capture, not the bezel. At a 150-190px phone
     frame it would otherwise wrap its own name into a two-line tower and drop
     the status pill onto a third line. */
  .device-shot > .device-caption {
    width: 100%;
  }

  .device-switcher {
    margin-top: 10px;
  }

  .device-thumbs {
    margin-top: 10px;
    padding: 2px 2px 6px;
    /* Re-stated after the shorthand so the button clearance survives the
       phone-sized padding. */
    padding-inline-end: var(--strip-tail);
  }

  .device-switcher-tabs {
    width: 100%;
  }

  .device-tab {
    flex: 1 1 0;
    min-height: 40px;
  }

  .device-thumb {
    /* Fixed, not shrinking: four tiles that each lose a few pixels to fit are
       four labels that all wrap at a different point. The strip scrolls and
       snaps instead, and every tile keeps the same width. */
    flex: 0 0 88px;
    width: 88px;
    min-height: 44px;
  }

  .device-thumb img {
    height: 50px;
  }
}

/* ── Reduced motion: keep every state, drop the movement ── */
@media (prefers-reduced-motion: reduce) {
  .device-frame,
  .device-tab,
  .device-thumb,
  .device-zoom,
  .project-card-showcase {
    transition: none;
  }

  .device-thumbs {
    scroll-behavior: auto;
  }

  .project-card-showcase:hover .device-frame {
    box-shadow: 0 20px 46px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35);
  }
}
