/* ==========================================================
   Design Engineering Experiments: the shelf
   App icons standing on frosted-glass planks, in the same family as
   the case-study folders. Tap an icon to open its card.
   ========================================================== */
.ps-sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------------- Shelf — same family as the case-study folders ----------------
   Every material, shadow, radius, type size and curve below is lifted from
   .case-folder* in style.css (or its --ease-folder-* tokens), so the shelf reads
   as a folder that holds apps instead of sheets:
     tray  = .case-folder-back   (#ebe9e4 paper, 1px white edge, 3-layer warm drop shadow, tab)
     ledge = .case-folder-flap   (frosted glass, inset white edge, upward contact shadow)
     icon  = .case-sheet         (sheet shadow, 1px hairline, rises on open)
     label = .case-folder-label  (12px/600 #252525 + 11px #747474)                       */
:root {
  --pf-paper: #ebe9e4;
  --pf-edge: rgba(255, 255, 255, 0.82);
  --pf-drop: drop-shadow(0 1px 2px rgb(65 59 49 / 0.06)) drop-shadow(0 7px 14px rgb(65 59 49 / 0.07)) drop-shadow(0 20px 34px rgb(65 59 49 / 0.08));
  --pf-flap: linear-gradient(to bottom, rgba(255, 255, 255, 0.72), rgba(250, 249, 246, 0.6));
  --pf-flap-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.72), 0 -2px 7px -2px rgba(65, 59, 49, 0.12);
  --pf-sheet-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 3px 8px rgba(0, 0, 0, 0.09);
  --pf-sheet-shadow-up: 0 0 0 1px rgba(0, 0, 0, 0.07), 0 10px 26px rgba(0, 0, 0, 0.14);
  --pf-strong: #252525;
  --pf-muted: #747474;
  --pf-arrow: #8d8d8d;
  --pf-scrim: rgba(250, 250, 250, 0.84);   /* the photo viewer's backdrop */
}
:root[data-theme="dark"] {
  --pf-paper: #262626; --pf-edge: rgba(255, 255, 255, 0.08);
  --pf-flap: linear-gradient(to bottom, rgba(45, 45, 45, 0.8), rgba(29, 29, 29, 0.72));
  --pf-flap-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 -2px 7px -2px rgba(0, 0, 0, 0.4);
  --pf-strong: #f0f0f0; --pf-muted: #a4a4a4; --pf-scrim: rgba(17, 17, 17, 0.84);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --pf-paper: #262626; --pf-edge: rgba(255, 255, 255, 0.08);
    --pf-flap: linear-gradient(to bottom, rgba(45, 45, 45, 0.8), rgba(29, 29, 29, 0.72));
    --pf-flap-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 -2px 7px -2px rgba(0, 0, 0, 0.4);
    --pf-strong: #f0f0f0; --pf-muted: #a4a4a4; --pf-scrim: rgba(17, 17, 17, 0.84);
  }
}

.ps-case {
  --icon: 72px;
  --slab: 62px;        /* frosted plank: its front carries the label */
  --lift: 5px;         /* icons stand on a shelf now, so a small rise */
  --top: 20px;
  --sink: 7px;         /* icons stand on the plank's top surface, a little in from its front edge */
  position: relative;
  padding: 14px 0;
  border-radius: 22px;
  background: var(--pf-paper);
  box-shadow: inset 0 0 0 1px var(--pf-edge);
  filter: var(--pf-drop);
}
.ps-shelf {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  row-gap: 14px;
  margin: 0; padding: 0 10px; list-style: none;
}
/* the plank: a slab of the folders' frosted glass, one per row, that the icons stand on */
.ps-ledge {
  grid-column: 1 / -1; align-self: end; z-index: 1;
  height: var(--slab);
  border-radius: 12px;
  /* top surface (lit) → front edge highlight → front face */
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2) 13px, rgba(255, 255, 255, 0.95) 13px, rgba(255, 255, 255, 0.95) 14px, rgba(255, 255, 255, 0) 14px), linear-gradient(to bottom, transparent 14px, rgb(65 59 49 / 0.04) 14px), var(--pf-flap);
  box-shadow: var(--pf-flap-shadow), 0 8px 14px -10px rgb(65 59 49 / 0.28);
  -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%);
  pointer-events: none;
}
:root[data-theme="dark"] .ps-ledge { background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03) 13px, rgba(255, 255, 255, 0.14) 13px, rgba(255, 255, 255, 0.14) 14px, rgba(255, 255, 255, 0) 14px), var(--pf-flap); box-shadow: var(--pf-flap-shadow), 0 8px 14px -10px rgba(0, 0, 0, 0.6); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .ps-ledge { background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03) 13px, rgba(255, 255, 255, 0.14) 13px, rgba(255, 255, 255, 0.14) 14px, rgba(255, 255, 255, 0) 14px), var(--pf-flap); box-shadow: var(--pf-flap-shadow), 0 8px 14px -10px rgba(0, 0, 0, 0.6); } }
.ps-item { position: relative; min-width: 0; padding-top: var(--top); }

.ps-app {
  all: unset; box-sizing: border-box;
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  width: 100%; min-width: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ps-face {
  position: relative; z-index: 2;
  display: block; overflow: hidden;
  width: var(--icon); height: var(--icon);
  margin-bottom: calc(var(--sink) * -1);
  border-radius: 22.5%;
  box-shadow: var(--pf-sheet-shadow);
  transform-origin: 50% 100%;
  transition: transform 300ms var(--ease-folder-close), box-shadow 180ms var(--ease-out);
}
.ps-face picture, .ps-refl picture { display: contents; }
.ps-face img { display: block; width: 100%; height: 100%; border-radius: 22.5%; object-fit: cover; }
.ps-face::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); pointer-events: none; }
/* reflection: the icon mirrored on the glass top, softened */
.ps-refl {
  position: absolute; z-index: 2; left: 50%; top: var(--icon);
  width: var(--icon); height: var(--icon); margin-left: calc(var(--icon) / -2);
  border-radius: 22.5%; overflow: hidden;
  transform: scaleY(-1); transform-origin: 50% 50%;
  opacity: 0.3;
  filter: blur(1.5px);   /* a soft reflection on the glass top */
  -webkit-mask-image: linear-gradient(to top, #000, transparent 20%); mask-image: linear-gradient(to top, #000, transparent 20%);
  transition: transform 300ms var(--ease-folder-close);
  pointer-events: none;
}
.ps-refl img { display: block; width: 100%; height: 100%; }
/* contact shadow where the icon meets the plank */
.ps-foot {
  position: absolute; z-index: 2; left: 50%; top: calc(var(--icon) - 4px);
  width: calc(var(--icon) * 0.8); height: 7px; margin-left: calc(var(--icon) * -0.4);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(65 59 49 / 0.4), transparent);
  transition: opacity 300ms var(--ease-folder-close), transform 300ms var(--ease-folder-close);
  pointer-events: none;
}
.ps-label {
  position: relative; z-index: 2;
  box-sizing: border-box;
  display: flex; flex-direction: column; justify-content: center;
  width: 100%; height: calc(var(--slab) - var(--sink));
  padding: 11px 8px 0;
  text-align: center;
}
.ps-label strong, .ps-label > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-label strong { color: var(--pf-strong); font-size: 12px; font-weight: 600; line-height: 1.45; letter-spacing: -0.01em; }
.ps-label > span { margin-top: 2px; color: var(--pf-muted); font-size: 11px; line-height: 1.45; letter-spacing: 0; }
.ps-label .lang-stack { display: inline-grid; }

/* hover = the folders' open: --ease-folder-open over 550ms in, --ease-folder-close over 300ms out */
@media (hover: hover) and (pointer: fine) {
  .ps-app:hover .ps-face {
    transform: translateY(calc(var(--lift) * -1));
    box-shadow: var(--pf-sheet-shadow-up);
    transition-duration: 550ms, 220ms;
    transition-timing-function: var(--ease-folder-open), var(--ease-out);
  }
  .ps-app:hover .ps-refl { transform: translateY(var(--lift)) scaleY(-1); transition: transform 550ms var(--ease-folder-open); }
  .ps-app:hover .ps-foot { opacity: 0.55; transform: scaleX(0.88); transition-duration: 550ms; transition-timing-function: var(--ease-folder-open); }
}
.ps-app:focus-visible { outline: none; }
.ps-app:focus-visible .ps-face {
  transform: translateY(calc(var(--lift) * -1));
  box-shadow: 0 0 0 3px var(--text), var(--pf-sheet-shadow-up);
  transition-duration: 550ms, 220ms;
  transition-timing-function: var(--ease-folder-open), var(--ease-out);
}
.ps-app:focus-visible .ps-refl { transform: translateY(var(--lift)) scaleY(-1); }
/* press = .case-folder:active */
.ps-app:active .ps-face { transform: translateY(calc(var(--lift) * -1)) scale(0.96); transition: transform 160ms var(--ease-out); }
.ps-app[data-ps-lifted] .ps-face, .ps-app[data-ps-lifted] .ps-refl { visibility: hidden; }
.ps-app[data-ps-lifted] .ps-foot { opacity: 0; }

/* Soon: an empty, icon-sized slot of the same frosted glass, outlined */
.ps-soon .ps-app { cursor: default; }
.ps-face-soon {
  background-image: var(--pf-flap);
  -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%);
  box-shadow: inset 0 0 0 1px var(--pf-edge);
  outline: 1.5px dashed color-mix(in srgb, var(--pf-muted) 45%, transparent); outline-offset: -1.5px;
}
.ps-face-soon::after { display: none; }
.ps-soon .ps-foot { opacity: 0.35; }

@media (max-width: 600px) {
  .ps-case { --icon: 58px; --slab: 57px; --lift: 4px; --top: 16px; --sink: 6px; padding: 10px 0; }
  .ps-shelf { padding: 0 6px; row-gap: 10px; }
  .ps-ledge { border-radius: 10px; }
  .ps-label { padding: 10px 3px 0; }
  .ps-label strong { font-size: 11.5px; }
  .ps-label > span { font-size: 10.5px; }
}
@media (max-width: 370px) { .ps-case { --icon: 54px; } }

/* ---------------- Detail card: the folder, opened ----------------
   Paper + tab + frosted flap; the preview is a sheet inside it. Opens on
   --ease-folder-open (550ms), closes on --ease-folder-close (300ms). */
.ps-card {
  width: min(520px, calc(100vw - 32px));
  max-width: none; max-height: calc(100dvh - 32px);
  margin: auto; padding: 0; border: 0; overflow: visible;
  background: transparent;
  color: var(--text);
}
/* Backdrop: a dimmed solid (the photo viewer's 84% scrim). Measured: a full-screen blur under an
   84%-opaque scrim was near-invisible but cost the most per frame, so it's gone. Only opacity moves. */
.ps-card::backdrop {
  background: var(--pf-scrim);
  opacity: 0; transition: opacity 180ms var(--ease-out);
}
.ps-card[data-shown]::backdrop { opacity: 1; transition-duration: 220ms; }
.ps-card-in {
  position: relative; display: flex; flex-direction: column;
  max-height: calc(100dvh - 32px);
  border-radius: 22px;
  background: var(--pf-paper);
  /* the folders' warm three-layer shadow as a static box-shadow: it rides along with the transform, never re-filtered */
  box-shadow: inset 0 0 0 1px var(--pf-edge), 0 1px 2px rgb(65 59 49 / 0.06), 0 7px 14px rgb(65 59 49 / 0.07), 0 24px 48px rgb(65 59 49 / 0.14);
  transform-origin: 0 0;
}
:root[data-theme="dark"] .ps-card-in { box-shadow: inset 0 0 0 1px var(--pf-edge), 0 24px 48px rgba(0, 0, 0, 0.5); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .ps-card-in { box-shadow: inset 0 0 0 1px var(--pf-edge), 0 24px 48px rgba(0, 0, 0, 0.5); } }
/* while moving: frosted panel swaps to a near-identical solid fill (no per-frame blur), blur returns on landing */
.ps-card[data-moving] .ps-card-body, .ps-card[data-moving] .ps-card-close { -webkit-backdrop-filter: none; backdrop-filter: none; background-color: color-mix(in srgb, var(--pf-paper) 88%, #fff); }
:root[data-theme="dark"] .ps-card[data-moving] .ps-card-body { background-color: #2a2a2a; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .ps-card[data-moving] .ps-card-body { background-color: #2a2a2a; } }
.ps-card[data-moving] .ps-card-icon { visibility: hidden; }
.ps-card-media {
  position: relative; z-index: 0;
  margin: 12px 12px 0; aspect-ratio: 16 / 10; flex: none;
  border-radius: 12px; overflow: hidden; background: #fff;
  box-shadow: var(--pf-sheet-shadow);
}
.ps-card-media picture, .ps-card-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ps-card-media img { outline: 1px solid rgba(0, 0, 0, 0.1); outline-offset: -1px; border-radius: 12px; }
.ps-card-body {
  position: relative; z-index: 1;
  margin-top: -36px;
  padding: 18px;
  border-radius: 16px 16px 22px 22px;
  background-image: var(--pf-flap);
  box-shadow: var(--pf-flap-shadow);
  -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%);
  overflow: auto; overscroll-behavior: contain;
}
.ps-card-head { display: flex; gap: 12px; align-items: center; }
.ps-card-icon { position: relative; flex: none; width: 40px; height: 40px; border-radius: 22.5%; overflow: hidden; box-shadow: var(--pf-sheet-shadow); }
.ps-card-icon picture { display: contents; }
.ps-card-icon img { display: block; width: 100%; height: 100%; }
.ps-card-title { margin: 0; color: var(--pf-strong); font-size: 15px; font-weight: 600; line-height: 1.4; letter-spacing: -0.01em; }
.ps-card-tag { margin: 1px 0 0; color: var(--pf-muted); font-size: 12px; line-height: 1.45; }
.ps-card-desc { margin: 12px 0 0; color: var(--text2); font-size: 13.5px; line-height: 1.6; letter-spacing: -0.005em; }
.ps-card-actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 14px; }
.ps-card-link {
  display: inline-flex; align-items: center; gap: 4px; min-height: 36px;
  color: var(--pf-strong); font-size: 12px; font-weight: 600; letter-spacing: -0.01em; text-decoration: none;
  transition: transform 160ms var(--ease-out);
}
.ps-card-link .lang-stack { display: inline-grid; }
/* same arrow, same nudge as .case-folder-label svg */
.ps-arrow-svg { flex: none; width: 16px; height: 16px; color: var(--pf-arrow); fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; transition: transform 180ms var(--ease-out), color 180ms ease; }
.ps-card-link:hover .ps-arrow-svg, .ps-card-link:focus-visible .ps-arrow-svg { color: var(--pf-strong); transform: translate(1px, -1px); }
.ps-card-link:active { transform: scale(0.96); }
.ps-card-link:focus-visible { outline: 2px solid var(--text); outline-offset: 4px; border-radius: 6px; }
.ps-card-kind { color: var(--pf-muted); font-size: 11px; }
.ps-card-close {
  all: unset; box-sizing: border-box; position: absolute; z-index: 2; top: 20px; right: 20px;
  display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; cursor: pointer;
  color: var(--pf-strong);
  background-image: var(--pf-flap); box-shadow: var(--pf-flap-shadow), 0 2px 6px rgba(0, 0, 0, 0.08);
  -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%);
  transition: transform 160ms var(--ease-out);
}
.ps-card-close:active { transform: scale(0.96); }
.ps-card-close:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.ps-ghost { position: fixed; left: 0; top: 0; z-index: 3; pointer-events: none; transform-origin: 0 0; overflow: hidden; border-radius: 22.5%; box-shadow: var(--pf-sheet-shadow-up); }
.ps-ghost img, .ps-ghost picture { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 600px) {
  .ps-card { margin-bottom: 16px; }
  .ps-card-media { margin: 10px 10px 0; }
  .ps-card-body { padding: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .ps-face, .ps-face::before, .ps-app::after { transition: none !important; }
  .ps-app:hover .ps-face::before { opacity: 0 !important; }
}
.ps-card-in:focus { outline: none; }

/* press-in on pointerdown (class set in JS so it starts the same frame) */
.ps-app[data-ps-press] .ps-face { transform: translateY(calc(var(--lift) * -1)) scale(0.94); transition: transform 120ms var(--ease-out); }
/* perf: while the card is up, the page sits under an 84% scrim, so its frosted layers can't be seen
   blurring anyway. Turning their live blur off for that time stops every animated frame from
   re-blurring the whole page (measured: open/close frames ~2x cheaper in software compositing). */
html:has(.ps-card[open]) :is(.ps-ledge, .ps-face-soon, .case-folder-flap) { -webkit-backdrop-filter: none; backdrop-filter: none; }
[data-ps-snap] .ps-face, [data-ps-snap] .ps-refl, [data-ps-snap] .ps-foot { transition: none !important; }

/* Coming soon: a real icon, set back behind the glass. Dimmed and slightly desaturated. It lifts on hover
   like the others (the tag rides along) but has nothing to open yet, so it isn't a button. */
.ps-coming .ps-face { opacity: 0.75; filter: saturate(0.8); box-shadow: none; }
.ps-coming .ps-refl { opacity: 0.22; }
/* the tag sits on the icon's top-right corner like an old home-screen badge, but quiet: paper on ink */
.ps-tag {
  position: absolute; z-index: 3; top: -6px; left: calc(50% + var(--icon) / 2 - 18px);
  width: max-content; padding: 2px 7px; border-radius: 999px;
  background: var(--pf-strong); color: var(--bg, #fff);
  font-size: 10px; font-weight: 600; line-height: 1.5; letter-spacing: 0.01em; white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
  transition: transform 300ms var(--ease-folder-close);
}
@media (hover: hover) and (pointer: fine) {
  .ps-coming .ps-app:hover .ps-tag { transform: translateY(calc(var(--lift) * -1)); transition: transform 550ms var(--ease-folder-open); }
}
.ps-tag .lang-stack { display: inline-grid; }
@media (max-width: 600px) { .ps-tag { top: -5px; left: calc(50% + var(--icon) / 2 - 16px); padding: 1px 6px; font-size: 9.5px; } }
