/* PocketArt — landing page.
   Palette lifted from the app's Theme.swift so the site and the product are
   demonstrably the same object: canvas F4EEE0, the three moulding golds, ink. */

:root {
  --canvas: #f4eee0;
  --canvas-deep: #eae1ce;
  --chrome: #fbf7ee;
  --mat: #fcfaf5;
  --gold-light: #b08a46;
  --gold-mid: #8a6a34;
  --gold-dark: #5a4322;
  --ink: #101014;
  --ink-2: #55555e;
  --ink-3: #8a8a93;
  --accent: #ef2773;
  --capture: #e8590c;
  /* A picture on a wall casts three shadows at once, and using only the big
     soft one — which is what this was — makes it read as floating rather than
     hanging. The tight contact shadow is what actually attaches it to the
     surface; the mid and ambient layers give the distance. Offset down and
     right, because the moulding is lit from the top left. */
  --shadow:
    2px 3px 4px -1px rgba(46, 32, 12, .30),
    7px 11px 18px -7px rgba(46, 32, 12, .34),
    16px 28px 44px -20px rgba(46, 32, 12, .38);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font: 17px/1.6 ui-rounded, "SF Pro Rounded", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
.serif { font-family: ui-serif, "New York", Georgia, "Times New Roman", serif; }

/* ---------------------------------------------------------------- the frame

   A frame is a profile, not a border: a run of concentric bands that step in
   and out on the way to the picture. Alternating light and dark across those
   bands is what makes a flat rectangle read as carved wood — the same trick
   the app draws in FrameStyle.swift, done here in one box-shadow. */

/* No mat. The 3px of white that used to sit between the picture and the
   moulding is a print convention, not a framing one — a panel is rebated
   straight into the wood, and on a 90px thumbnail the white line read as a
   sticker border rather than as card. `background` stays for .quiz-art, which
   sets its own padding and does want the mat. */
.frame {
  position: relative;
  display: block;
  background: var(--mat);
  padding: 0;
  /* The moulding is held in its own property so `:hover` can swap the drop
     shadow underneath it without having to restate every band — which is what
     pinned all twelve pictures to the one gilt profile before. */
  --moulding:
    0 0 0 2px var(--gold-light),
    0 0 0 5px var(--gold-mid),
    0 0 0 6px var(--gold-dark),
    0 0 0 9px var(--gold-light),
    0 0 0 10px var(--gold-dark);
  box-shadow: var(--moulding), var(--shadow);
  transition: transform .5s cubic-bezier(.2, .8, .2, 1), box-shadow .5s;
}
.frame img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* ------------------------------------------------------------- the mouldings

   The six profiles the app carves in FrameStyle.swift, ported band for band so
   the wall here and the wall in the product are the same furniture. A frame is
   not a coloured border but a strip of wood that steps in and out on its way to
   the picture; alternating light and dark across those steps is what makes a
   flat rectangle read as carving.

   The app lists its bands outermost-first and draws inward. box-shadow stacks
   the opposite way — first rule on top, spread growing outward — so these are
   the same runs reversed, with each band's share of the moulding width turned
   into a cumulative spread. */

/* Wide, warm and heavily worked: a salon frame. */
.frame.gilt {
  --moulding:
    0 0 0 2px #46320f, 0 0 0 3px #d8bc5c, 0 0 0 5px #8a6a2e,
    0 0 0 7px #e8ce7a, 0 0 0 9px #74551f, 0 0 0 12px #c9a227,
    0 0 0 13px #5e4419;
}
/* The Dutch ripple: near-black pearwood cut on a wave engine, so the face is a
   run of fine ridges. Ten 1px bands is what that costs. */
.frame.ripple {
  --moulding:
    0 0 0 1px #3a2f26, 0 0 0 2px #1e1712, 0 0 0 3px #4e4034,
    0 0 0 4px #231b15, 0 0 0 5px #62513f, 0 0 0 6px #281f19,
    0 0 0 7px #685646, 0 0 0 8px #2c231b, 0 0 0 9px #5a4b3c,
    0 0 0 10px #241c16;
}
/* A cassetta: broad flat walnut face between two narrow raised edges. Quiet,
   and what most smaller pictures actually hung in. */
.frame.cassetta {
  --moulding:
    0 0 0 3px #2e2116, 0 0 0 4px #8a6540, 0 0 0 8px #6b4a2e,
    0 0 0 9px #8a6540, 0 0 0 11px #3a2a1c;
}
/* Narrow gilt, for later work that wanted less ceremony. */
.frame.slim {
  --moulding:
    0 0 0 1px #5e4419, 0 0 0 4px #d9b44a, 0 0 0 5px #7a5a28;
}
/* A Florentine scoop: a hollow between two raised edges, all water gilded. */
.frame.florentine {
  --moulding:
    0 0 0 2px #dcbe68, 0 0 0 4px #6a4c18, 0 0 0 7px #8a6626,
    0 0 0 8px #e3c878, 0 0 0 10px #b98f2e;
}
/* Ebonised wood with a bright gold sight edge — the Spanish and Flemish answer
   to the gilt frame. The thin gold line at the picture is what keeps it from
   reading as a hole in the wall. */
.frame.ebony {
  --moulding:
    0 0 0 2px #c9a227, 0 0 0 3px #120d0a, 0 0 0 4px #3a2e22,
    0 0 0 6px #1b1410, 0 0 0 8px #2a2018;
}

/* ------------------------------------------------------------------- shared */

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 24px; }
h1, h2, h3 { letter-spacing: -.03em; line-height: 1.04; margin: 0; font-weight: 800; }
.eyebrow {
  font-size: 13px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold-mid); margin: 0 0 14px;
}
.lede { color: var(--ink-2); font-size: 19px; max-width: 46ch; }

.btn {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--ink); color: var(--canvas);
  padding: 15px 26px; border-radius: 999px;
  font-size: 16px; font-weight: 700; text-decoration: none;
  transition: transform .25s cubic-bezier(.2,.8,.2,1), box-shadow .25s;
  box-shadow: 0 10px 24px -12px rgba(16,16,20,.7);
}
.btn-ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px rgba(16,16,20,.16); }

/* -------------------------------------------------------------- store badge

   Apple's own artwork, served locally. Their identity guidelines ask that the
   badge is used as supplied rather than rebuilt, and that it is given clear
   space of at least a quarter of its height — hence the margin, rather than
   letting the note below sit tight against it. */

.badge {
  display: inline-block;
  line-height: 0;
  transition: transform .25s cubic-bezier(.2, .8, .2, 1), opacity .25s;
}
/* No drop shadow. The badge is a supplied piece of artwork with its own
   rounded rect, and hanging a shadow off it makes it read as a screenshot of a
   button rather than as the badge. */
.badge img { height: 58px; width: auto; display: block; }
nav .nav-badge img { height: 40px; }
.hero-cta .badge, .close .badge { margin-block: 4px 16px; }

@media (max-width: 780px) {
  /* Only the page badges shrink here. Left as a bare `.badge img` this also
     caught the one in the nav, which then collided with the wordmark. */
  .hero-cta .badge img, .close .badge img { height: 52px; }
  nav .nav-badge img { height: 34px; }
}

/* ---------------------------------------------------------------------- nav */

nav {
  position: fixed; inset: 0 0 auto; z-index: 60;
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 28px;
  backdrop-filter: blur(14px);
  background: color-mix(in srgb, var(--canvas) 72%, transparent);
  border-bottom: 1px solid transparent;
  transition: border-color .3s, background .3s;
}
nav.scrolled { border-bottom-color: var(--canvas-deep); }
nav .brand { display: flex; align-items: center; gap: 11px; font-weight: 800; font-size: 17px; text-decoration: none; color: var(--ink); }
/* The squircle is baked into the PNG's alpha, so no radius here — a
   border-radius on top would only clip the corners a second time, and at a
   different curve to the one iOS actually draws. */
nav .brand img { width: 32px; height: 32px; filter: drop-shadow(0 2px 5px rgba(46,32,12,.42)); }
nav .links { display: flex; align-items: center; gap: 26px; }
nav .links a { color: var(--ink-2); text-decoration: none; font-size: 15px; font-weight: 600; }
nav .btn { padding: 10px 20px; font-size: 15px; }

/* --------------------------------------------------------------------- hero

   The paintings hang on the perimeter of a grid and the words sit in the hole
   in the middle — a salon wall with a gap where the label would be. */

/* `minmax(0, 1fr)` rather than the implicit `auto`, so a wide child can never
   push the track past the viewport and scroll the page sideways. */
.hero {
  position: relative; min-height: 100svh;
  display: grid; grid-template-columns: minmax(0, 1fr);
  place-items: center; padding: 96px 0 40px;
}

/* Absolutely placed rather than gridded. Each picture is anchored to the edge
   it is nearest, sized by its own height and left to work out its width, so the
   wall keeps its proportions and its overlaps at any viewport. */
.gallery { position: absolute; inset: 0; pointer-events: none; }

/* Rotation, scale and offset are written as the independent `rotate`, `scale`
   and `translate` properties rather than packed into one `transform`.
   With a single `transform` the entrance animation and the hover would be the
   same property, and an animation that fills forwards outranks a hover rule —
   so the pictures would land and then refuse to respond to the pointer. */
.gallery .slot {
  position: absolute;
  pointer-events: auto;
  z-index: var(--z, 1);
  rotate: var(--rot);
  animation: hang .75s cubic-bezier(.18, .9, .26, 1.08) backwards;
  transition: rotate .45s cubic-bezier(.2, .9, .25, 1.1),
              scale .45s cubic-bezier(.2, .9, .25, 1.1),
              translate .45s cubic-bezier(.2, .9, .25, 1.1);
}

/* Dropped in overshot and off-angle, then settling. `backwards` rather than
   `forwards`: the resting state is the element's own styles, which is what
   leaves hover free to take over once the picture has landed. */
@keyframes hang {
  from { opacity: 0; translate: 0 -26px; scale: .86; rotate: calc(var(--rot) * 2.4); }
}

.gallery .frame { display: block; }
.gallery .frame img {
  /* Sized in vh, but capped against the width. A tall narrow window makes vh
     large while leaving no horizontal room, so the pictures ballooned to 376px
     and walked over the headline. The cap only bites in that shape — on a normal
     landscape desktop the vh figure is the smaller of the two and still wins. */
  height: min(var(--h), 19vw);
  width: auto;
  max-width: 30vw;
  display: block;
}
.hero-copy { position: relative; z-index: 10; text-align: center; max-width: 640px; padding: 0 20px; }
.hero-copy h1 { font-size: clamp(44px, 7.2vw, 88px); }
/* The second line was gold, which measured 4.33:1 on the cream — passing for
   display type but the weakest text on a page where it is the loudest thing
   said. In ink it is 16.4:1, and the colour is left to the paintings. The line
   break carries the emphasis on its own. */
.hero-copy h1 em { font-style: normal; color: inherit; }
.hero-copy .lede { margin: 22px auto 0; font-size: clamp(17px, 2vw, 21px); }
.hero-cta { display: flex; gap: 12px; justify-content: center; margin-top: 30px; flex-wrap: wrap; }
.hero-note { margin-top: 18px; font-size: 14px; color: var(--ink-3); }

/* Only wide enough to keep the words off the wallpaper. The first pass reached
   into the side columns and left the pictures next to the headline half
   dissolved, which read as images failing to load rather than as depth. */
.hero-veil {
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background: radial-gradient(ellipse 30% 27% at 50% 52%,
    var(--canvas) 0%, var(--canvas) 55%, color-mix(in srgb, var(--canvas) 65%, transparent) 76%, transparent 100%);
}

/* ----------------------------------------------------------------- sections */

section.band { padding: 120px 0; }
.reveal { opacity: 0; transform: translateY(26px); transition: opacity .8s cubic-bezier(.2,.8,.2,1), transform .8s cubic-bezier(.2,.8,.2,1); }
.reveal.in { opacity: 1; transform: none; }

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 72px; align-items: center; }
.split h2 { font-size: clamp(32px, 4vw, 46px); margin-bottom: 18px; }
.split p { color: var(--ink-2); font-size: 18px; }

/* The parcel that opens as it scrolls past — the app's core moment, on a page. */
.unwrap { position: relative; aspect-ratio: 1024 / 1536; max-width: 380px; margin: 0 auto; width: 100%; }
.unwrap .frame { position: absolute; inset: 0; }
.unwrap .paper {
  position: absolute; inset: -2%; z-index: 3;
  background-size: cover; background-position: center;
  border-radius: 2px;
  box-shadow: var(--shadow);
  clip-path: inset(0 0 0 0);
  transition: clip-path 1.1s cubic-bezier(.65, 0, .35, 1);
}
.unwrap.opened .paper { clip-path: inset(0 0 0 100%); }

/* -------------------------------------------------------------- phone mockup

   Drawn rather than shipped as a PNG bezel: the proportions come from the
   recording itself (1180x2556, an iPhone 15/16 Pro), and every radius is a
   percentage of that, so the whole thing scales without a single fixed pixel
   and without a two-hundred-kilobyte device frame image. */

.phone {
  position: relative;
  width: min(300px, 74vw);
  aspect-ratio: 1180 / 2556;
  margin: 0 auto;
}

/* The band of titanium. Lit from the top left like everything else on the
   page, with a brighter rim where the edge catches. */
.phone-body {
  position: absolute; inset: 0;
  padding: 2.4%;
  border-radius: 13.2% / 6.1%;
  background: linear-gradient(148deg, #6b6b70 0%, #26262a 18%, #17171a 52%, #35353a 82%, #5c5c61 100%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .14),
    3px 4px 6px -2px rgba(46, 32, 12, .30),
    10px 16px 26px -8px rgba(46, 32, 12, .34),
    22px 38px 60px -22px rgba(46, 32, 12, .40);
}

.phone-screen {
  position: relative;
  width: 100%; height: 100%;
  border-radius: 11.4% / 5.3%;
  overflow: hidden;
  background: #000;
}
.phone-screen video {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

/* The red screen-recording dot, covered in the Dynamic Island's own black —
   it sits inside the island, so the patch is invisible.
   Position measured off a frame of the video and written as a percentage, so
   it holds at any mockup size. */
.hide-rec { position: absolute; z-index: 1; border-radius: 999px; }
.hide-rec { left: 29.6%; top: 2.4%; width: 4.6%; height: 2.0%; background: #090907; }

.phone-island {
  position: absolute; z-index: 2;
  top: 3.1%; left: 50%; transform: translateX(-50%);
  width: 30%; height: 3.1%;
  background: #000;
  border-radius: 999px;
}

@media (max-width: 1080px) {
  /* The split stacks here, so the phone stops being a column and needs to not
     tower over the paragraph that follows it. */
  .phone { width: min(260px, 62vw); }
}

/* -------------------------------------------------------------------- steps */

.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; margin-top: 56px; }
.card {
  background: var(--chrome); border: 1px solid var(--canvas-deep);
  border-radius: 22px; padding: 30px 28px;
  transition: transform .4s cubic-bezier(.2,.8,.2,1), box-shadow .4s;
}
.card .n { font-size: 13px; font-weight: 800; color: var(--gold-mid); letter-spacing: .14em; }
.card h3 { font-size: 22px; margin: 12px 0 10px; }
.card p { color: var(--ink-2); font-size: 16px; margin: 0; }

/* ---------------------------------------------------------------------- quiz

   Every part of this card is a fixed height. The painting block, the question
   and the four options do not change size between questions, so the card never
   grows or shrinks — which is what stopped the copy in the left column drifting
   up and down each time the round advanced. */

.quiz {
  position: relative; overflow: hidden;
  background: var(--chrome); border: 1px solid var(--canvas-deep);
  border-radius: 24px; max-width: 420px;
  box-shadow: 0 24px 48px -34px rgba(46, 32, 12, .55);
}
.quiz .confetti { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 4; }

/* The swap. Both halves fade and lift together, so one question leaves and the
   next arrives rather than the card blinking its contents. */
.quiz-art, .quiz-body { transition: opacity .26s ease, translate .26s ease; }
.quiz.swapping .quiz-art,
.quiz.swapping .quiz-body { opacity: 0; translate: 0 -6px; }

.quiz-art {
  display: grid; place-items: center;
  height: 196px;                 /* fixed, not min: a portrait and a landscape
                                    have to occupy exactly the same block */
  padding: 26px 26px 0;
}

/* A quieter moulding than the wall outside. The full five-band gilt is right on
   a page of paintings and far too loud inside a card this size. */
.quiz-art .frame {
  padding: 2px;
  box-shadow: 0 0 0 1px var(--gold-mid), 0 0 0 4px var(--mat), 0 0 0 5px rgba(90, 67, 34, .28),
              0 12px 22px -14px rgba(46, 32, 12, .6);
  transition: scale .5s cubic-bezier(.2, .8, .2, 1);
}
.quiz-art .frame img { max-height: 170px; width: auto; max-width: 100%; }
.quiz.correct .quiz-art .frame { scale: 1.035; }

.quiz-body { padding: 20px 26px 26px; }

.dots { display: flex; gap: 5px; margin-bottom: 15px; }
.dots i {
  width: 20px; height: 3px; border-radius: 2px;
  background: var(--canvas-deep); transition: background .3s;
}
.dots i.done { background: var(--gold-light); }
.dots i.now { background: var(--ink); }

.quiz .q {
  font-size: 18px; font-weight: 700; margin: 0 0 16px;
  height: 52px;                  /* two lines, always */
  /* Not flex. The question is one sentence with an italic <span> inside it, and
     flex makes the span and the text either side of it three separate items —
     which is why it read "Who painted / Girl with a Pearl / ? / Earring". */
  display: block;
}

/* The title is serif italic set inside upright sans, and the two faces sit too
   close where they meet. A couple of pixels either side, not a real space —
   a word space here would look like a typo. */
.quiz .q .serif { margin-inline: 2px; }

.quiz .opt {
  display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left;
  padding: 13px 16px; margin-bottom: 8px;
  border-radius: 12px; background: var(--canvas);
  border: 1px solid var(--canvas-deep);
  font: inherit; font-size: 15.5px; font-weight: 600; color: var(--ink);
  cursor: pointer;
  transition: border-color .25s ease, background .25s ease, translate .25s ease, opacity .25s ease;
}
.quiz .opt:last-child { margin-bottom: 0; }
.quiz .opt:disabled { cursor: default; }
.quiz .opt .mark { margin-left: auto; font-size: 14px; font-weight: 800; opacity: 0; scale: .6; transition: opacity .3s, scale .3s cubic-bezier(.2, 1.6, .4, 1); }
.quiz .opt.right { border-color: #2f7a52; background: color-mix(in srgb, #2f7a52 12%, var(--canvas)); }
.quiz .opt.right .mark { color: #2f7a52; opacity: 1; scale: 1; }
.quiz .opt.wrong { border-color: #b03a2e; background: color-mix(in srgb, #b03a2e 10%, var(--canvas)); }
.quiz .opt.wrong .mark { color: #b03a2e; opacity: 1; scale: 1; }
.quiz .opt.faded { opacity: .4; }

.quiz-done { display: none; text-align: center; padding: 0 26px; place-content: center; }
.quiz.finished .quiz-body, .quiz.finished .quiz-art { display: none; }
/* Holds the height the two hidden halves were occupying, so finishing the round
   cannot collapse the card and shunt the paragraph beside it. */
.quiz.finished { display: grid; min-height: 540px; }
.quiz.finished .quiz-done { display: grid; }
.quiz-done .score { font-size: 42px; font-weight: 800; letter-spacing: -.03em; margin: 0 0 6px; }
.quiz-done .verdict { color: var(--ink-2); margin: 0 0 22px; }

/* --------------------------------------------------------------------- close */

.close { text-align: center; padding: 130px 0 120px; }
.close h2 { font-size: clamp(36px, 5.4vw, 62px); margin-bottom: 20px; }
/* The shadow is painted into the PNG, not applied as a filter. A CSS
   drop-shadow on a child of a fading section is rasterised only once the
   transition settles, so the shadow popped in a frame after the icon —
   most visibly on a phone. Baked in, there is nothing left to re-rasterise.
   The artwork occupies the middle 80% of the file; the rest is the shadow's
   room, which is why the box is 130px for a 104px icon. */
.close img.appicon { width: 130px; height: 130px; margin-bottom: 22px; }

footer { border-top: 1px solid var(--canvas-deep); padding: 34px 0 60px; color: var(--ink-3); font-size: 15px; }
footer .wrap { display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
footer a { color: var(--ink-2); text-decoration: none; margin-left: 22px; }
footer a:first-child { margin-left: 0; }

/* ---------------------------------------------------------------- responsive */

@media (max-width: 1080px) {
  .split { grid-template-columns: 1fr; gap: 44px; }
  .steps { grid-template-columns: 1fr; }
}
@media (max-width: 780px) {
  nav .links { display: none; }

  /* Four pictures in the corners instead of twelve, still, and clear of the
     words. No entrance either: on a screen this size the animation is the first
     thing you see and it delays the only thing worth reading. */

  /* Full height, not 92svh. The eight per cent left over showed as a band of
     bare cream under the bottom pair — too short to read as the next section
     starting, so it read as the page running out. Owning the whole screen puts
     that space back under the pictures, and the extra top padding drops the
     column of words below the halfway line where it was sitting. */
  .hero { min-height: 100svh; padding: 112px 0 28px; }
  .gallery .slot { animation: none; }
  /* The cap here is the size, not a safety rail. `--h` is in vh, and at this
     width 19vw is smaller than every vh figure the wall asks for — so all four
     pictures came out at the same 71px and the per-picture heights did nothing.
     Raising it to 30vw lets `--h` govern again, which is what gives the bottom
     pair its weight. max-width has to stay ahead of the widest frame at that
     height (Venus is 1.56:1, so ~47vw) or a fixed height plus a biting
     max-width squeezes the picture out of its aspect ratio. */
  .gallery .frame img { height: min(var(--h), 30vw); max-width: 50vw; }
  .hero-copy h1 { font-size: clamp(38px, 12vw, 54px); }

  /* Tucked up under the button rather than floating between it and the
     pictures below — it is a footnote to the button, so it should read as
     attached to it. */
  .hero-note { margin-top: 10px; }

  section.band { padding: 84px 0; }
}

/* Short phones — an SE is 667px where a modern iPhone is 812–932. The column of
   words is a fixed height and the screen is not, so the same percentages that
   leave 51px between the small print and the bottom pair on a 14 leave 3px on
   an SE, and Venus sits on the line. Nothing here is a different layout: the
   air inside the copy comes in a little and the pictures come down a size, so
   the gap survives. */
@media (max-width: 780px) and (max-height: 740px) {
  .hero { padding: 88px 0 20px; }
  .hero-copy .lede { margin-top: 16px; }
  .hero-cta { margin-top: 20px; }
  .gallery .frame img { height: min(var(--h), 26vw); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .gallery .slot { opacity: 1; }
  .reveal { opacity: 1; transform: none; }
  .unwrap .paper { clip-path: inset(0 0 0 100%); }
}


/* -------------------------------------------------------------- hover only

   Every hover state lives behind this query. A touch browser has no hover, but
   it will happily apply :hover to whatever was last under a finger and leave it
   there — which is why one quiz option sat with a gold border on the phone
   without anyone having tapped it. */

@media (hover: hover) and (pointer: fine) {
  .btn:hover { transform: translateY(-2px); box-shadow: 0 16px 30px -12px rgba(16,16,20,.75); }
  .btn-ghost:hover { box-shadow: inset 0 0 0 1.5px rgba(16,16,20,.34); }
  .badge:hover { transform: translateY(-2px); opacity: .88; }
  nav .links a:hover { color: var(--ink); }
  .card:hover { transform: translateY(-5px); box-shadow: 0 22px 44px -26px rgba(46,32,12,.6); }
  .quiz .opt:hover:not(:disabled) { translate: 3px 0; border-color: var(--gold-light); }
  footer a:hover { color: var(--ink); }
  /* Hover pulls the picture straight, forward and up — the gesture of lifting
     one off the wall to look at it properly. */
  .gallery .slot:hover {
    z-index: 20;
    rotate: 0deg;
    scale: 1.13;
    translate: 0 -10px;
  }
  /* The picture's own moulding, over a longer shadow — lifting it off the wall
     must not also re-carve the frame. */
  .gallery .slot:hover .frame {
    box-shadow: var(--moulding),
      4px 6px 8px -2px rgba(46, 32, 12, .30),
      14px 22px 34px -12px rgba(46, 32, 12, .38),
      34px 54px 78px -26px rgba(46, 32, 12, .42);
  }
}
