/* Raw-card slab — the Vaultr case a raw (ungraded) card is presented in.
   ---------------------------------------------------------------------------
   The case is a rendered image (static/img/raw-slab.webp, transparent outside
   the acrylic): a clear one-touch slab with a Vaultr label across the top that
   says RAW / UNGRADED, so it cannot be read as a grade. The scan is seated into
   the case's card window by percentage coordinates measured off that render:
   window left 11.68% top 24.81% width 76.78% height 65.15% of the image, whose
   own aspect is 788:1294. Change the image and these numbers change with it.

   The shell WRAPS the card's existing container rather than becoming it. In
   the reveal that container is .po-card-face, which the pack-tear hand-off
   measures to scale the flight card into — the slab has to be the same shape
   at both ends, which is why the rip engine's card frame is sized to the same
   788:1294 (pack-tear.js, SLAB_IMG_ASPECT). */

/* The label under RAW names the card's CONDITION, in its colour (Andrew,
   2026-09-16), where the original render says UNGRADED. One render per
   condition (scripts/make_raw_slab_conditions.py), picked by a data-cond
   attribute holding the condition name — on the case itself or any ancestor,
   since the custom property inherits. No data-cond, or one we don't know, and
   the case falls back to the original UNGRADED render rather than breaking. */
[data-cond="Near Mint" i]         { --rs-slab: url("/static/img/raw-slab-nm.png"); }
[data-cond="Lightly Played" i]    { --rs-slab: url("/static/img/raw-slab-lp.png"); }
[data-cond="Moderately Played" i] { --rs-slab: url("/static/img/raw-slab-mp.png"); }
[data-cond="Heavily Played" i]    { --rs-slab: url("/static/img/raw-slab-hp.png"); }
[data-cond="Damaged" i]           { --rs-slab: url("/static/img/raw-slab-dmg.png"); }

.rawshell {
    --rs-fs: 11px;
    /* Window (the render's card aperture), as shares of the case's box. */
    --rs-wl: 11.22%; --rs-wt: 24.57%; --rs-ww: 77.55%; --rs-wh: 64.96%;
    /* Cavity gap between the card and the aperture's lip. 1cqi = 1% of the
       case's width, so every depth cue below scales with the case. */
    --rs-gap: 1.1cqi;
    position: relative;
    display: block;
    width: 100%;
    max-width: 100%;
    aspect-ratio: 788 / 1294;
    container-type: inline-size;
    line-height: 0;
    color: #f5f7f4;
    background: var(--rs-slab, url("/static/img/raw-slab-original.png")) 50% 48.78% / 130.61% 119.07% no-repeat;
    /* The case's outline: the image's 140px corner against each axis of its
       788x1296 box. Every layer that must not leave the acrylic (the shadow
       below, the reflection) is clipped to this. */
    --rs-r: 6.76% / 4.11%;
    border-radius: var(--rs-r);
    /* The object floats on the page, so one coherent floating shadow: no
       base contact shadow (that is a standing slab, a different spatial cue).
       box-shadow, not filter: drop-shadow(): a filter re-rasterises the whole
       case every frame anything inside it animates (the tier halo pulses),
       which is what made the reveal stutter. */
    box-shadow: 0 18px 30px rgba(0,0,0,0.42);
}
.rawshell > * { position: absolute; z-index: 2; }

/* Layer 3/4/5 — the card, seated in the cavity. The render's aperture is the
   dark matte backing; the card sits inside it with a narrow, even gap so the
   backing shows around every edge, and a tight contact shadow falls from the
   card onto that backing. Aspect ratio is the scan's own (object-fit:
   contain; the aperture is 0.718 and a card is 0.714, so nothing is cropped
   and any letterbox is sub-1% of dark-on-dark). The only rounding is the
   card's own corners, which the scan already carries. */
.rawshell > :not(.rawshell-lip) {
    left: calc(var(--rs-wl) + var(--rs-gap));
    top: calc(var(--rs-wt) + var(--rs-gap));
    width: calc(var(--rs-ww) - 2 * var(--rs-gap));
    height: calc(var(--rs-wh) - 2 * var(--rs-gap));
    border-radius: 0.9cqi;
    overflow: hidden;
    background: transparent;
    box-shadow:
        0 0 0 0.12cqi rgba(0,0,0,0.55),
        0 0.25cqi 0.5cqi rgba(0,0,0,0.55),
        0 0.7cqi 1.4cqi rgba(0,0,0,0.30);
}
.rawshell > :not(.rawshell-lip) img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    padding: 0;
    border-radius: 0;
}

/* Layer 6 — the retaining lips. The front lip sits above the card, so its
   shadow falls inward onto the card's edge: a short occlusion from the top
   and sides, fading out before it reaches any printed content. Drawn over the
   aperture as a whole, so it also darkens the gap. */
.rawshell::before,
.pt-card.pt-raw .pt-face::before,
#stage-result .po-card-face.po-slot-hosts-flight .pt-card.pt-raw .pt-face::before {
    content: "";
    position: absolute;
    left: var(--rs-wl); top: var(--rs-wt); width: var(--rs-ww); height: var(--rs-wh);
    z-index: 3;
    border-radius: 2.2cqi;
    background:
        linear-gradient(180deg, rgba(0,0,0,0.23) 0%, rgba(0,0,0,0.07) 2.2%, rgba(0,0,0,0) 5%),
        linear-gradient(90deg,  rgba(0,0,0,0.16) 0%, rgba(0,0,0,0) 3%),
        linear-gradient(270deg, rgba(0,0,0,0.12) 0%, rgba(0,0,0,0) 3%),
        linear-gradient(0deg,   rgba(0,0,0,0.16) 0%, rgba(0,0,0,0) 2.5%);
    pointer-events: none;
}

/* Layer 7 — the front plate. The render already carries the perimeter bevel
   and the thick-edge highlights; the flat window is optically clear. What is
   added is ONE soft reflection band from the upper-left key light, crossing
   the whole front plate — label and card alike — at low contrast, so it
   reads as the plate and not as a haze. Clipped to the case's outline. */
.rawshell::after,
.pt-card.pt-raw .pt-face::after,
#stage-result .po-card-face.po-slot-hosts-flight .pt-card.pt-raw .pt-face::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 4;
    /* Clipped by the case image's own alpha, so the band can never show past
       the acrylic's rounded corner as a pale square. */
    border-radius: var(--rs-r);
    overflow: hidden;
    clip-path: inset(0 round 6.76% / 4.11%);
    background:
        linear-gradient(112deg,
            rgba(255,255,255,0) 20%, rgba(255,255,255,0.075) 29%,
            rgba(255,255,255,0.105) 33%, rgba(255,255,255,0.03) 38%,
            rgba(255,255,255,0) 44%);
    pointer-events: none;
}

/* Nothing is printed on the case beyond what the render carries (founder,
   2026-09-15: "remove the text at the bottom, leave the logo"). The label
   rows still arrive from the templates and the rip engine; they just don't
   paint. Condition and code are shown by the surfaces around the case. */
.rawshell-lip, .rawshell-lip-bare, .pt-card.pt-raw .rawshell-lip { display: none; }

/* ── per-surface ─────────────────────────────────────────────────────────── */

/* Reveal. The shell sits INSIDE .po-card-face (see the header note). The
   face keeps its own tier glow and pulse, so the halo lights the case. */
.po-card-face > .rawshell {
    --rs-fs: 12px;
    /* A graded scan is an <img> and gives the slot its size; the case is a
       background image with no intrinsic size, so it must carry a width or
       the slot is 0x0 and the info column lays out over it. 240px is what the
       graded scan resolves to on desktop; the phone width mirrors
       pack-opening.css's `#stage-result .po-card-face > img` rule. */
    width: 240px;
    max-width: 100%;
    margin: 0 auto;
}
@media (max-width: 900px) {
    .po-card-face > .rawshell { width: min(49.5vw, 215px); }
}
/* The slot's own border, plate and halo are drawn for a rectangular scan; the
   case has rounded, transparent corners, so they would show as a box around
   it. The case carries its own drop shadow. */
#stage-result .po-card-face:has(> .rawshell) {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    animation: none;
}
/* ...and the slot's rectangular chrome: its ::after halo plate and the
   animated edge-trace runners are drawn to the slot's 12px box, which a
   rectangular slab scan covers and the round case does not (a pale square
   behind the case, and a stroke running round it). */
#stage-result .po-card-face:has(> .rawshell)::before,
#stage-result .po-card-face:has(> .rawshell)::after,
#stage-result .po-card-face:has(> .rawshell) .po-edge-trace {
    display: none;
}
/* The landed tier halo (.po-card-glow) is a 14px-radius rectangle sized to the
   card's box; behind the round case it read as a pale square. Same halo,
   the case's outline. */
#stage-result .po-card-reveal:has(> .po-card-face > .rawshell) .po-card-glow {
    inset: -12% -18%;
    border-radius: 50%;
    box-shadow: none;
    background: radial-gradient(ellipse at 50% 50%,
        rgba(var(--tier-rgb, 148,163,184), 0.42) 0%,
        rgba(var(--tier-rgb, 148,163,184), 0.16) 45%,
        rgba(var(--tier-rgb, 148,163,184), 0) 72%);
}

/* Decision grid — session summary and /my-pulls. The tile keeps the slab's
   7/12 shape so its title, price and buttons sit level with the graded
   slabs beside it; the case is centred in it. The strip's type is sized off
   the case's own width (cqi): the tile is 210px on desktop and 150px on a
   phone. */
.ss-card[data-raw="1"] .ss-card-slab {
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    animation: none;
}
/* The flip box takes the case's shape (the tile is 7/12, the case 788/1294)
   and each FACE is a case, so the case turns with the card instead of
   standing still while the scan spins inside its window. */
.ss-card[data-raw="1"] .ss-flip {
    position: relative;
    inset: auto;
    width: 100%;
    aspect-ratio: 788 / 1294;
}
.ss-flip-face.ss-rawshell,
[data-celebrate] .ss-card-slab .ss-flip-face.ss-rawshell {
    --rs-fs: 4.8cqi;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    padding: 0;
    container-type: inline-size;
    border-radius: var(--rs-r);
}
.ss-flip-face.ss-rawshell > img,
[data-celebrate] .ss-card-slab .ss-flip-face.ss-rawshell > img {
    padding: 0;
    object-fit: contain;
}
.ss-card-sold .ss-flip-face.ss-rawshell, .ss-card-vaulted .ss-flip-face.ss-rawshell { filter: none; }

/* Just Pulled tile: one case per FACE, inside the flip inner, so the case
   turns with the card. The back scan's inline transform/position
   (jp_tile.html) are the face's job now, and the tile's own drop-shadow on
   the scan is replaced by the case's contact shadow. */
.jp-flip-inner > .rawshell {
    --rs-fs: 8px;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}
.jp-flip-inner > .rawshell.jp-face-back {
    position: absolute;
    inset: 0;
    transform: rotateY(180deg);
}
.jp-flip-inner > .rawshell > .rs-win {
    display: flex;
    align-items: center;
    justify-content: center;
}
.jp-flip-inner > .rawshell > .rs-win > img {
    position: static !important;
    transform: none !important;
    filter: none !important;
    border-radius: 0 !important;
}
/* The phone tile's container is width:auto (home_just_pulled.html) and takes
   its width from the scan's intrinsic size. A case has none (its image is a
   background), so the 100% chain resolved to 0x0 and every raw tile was an
   empty stage in the app and on phone web (2026-09-15). Desktop pins 74%. */
.home-just-pulled .jp-stage .jp-flip-container:has(.rawshell) {
    width: 74% !important;
    max-width: 74% !important;
}

/* Multi-pack session: the card sitting under the sealed pack. The reveal's own
   faces already override to aspect-ratio:auto + contain, so only this one is
   still carrying the slab shape. */
[data-raw="1"] .sr-card-shape { aspect-ratio: 5 / 7; }

/* Grid tiles elsewhere (.card-img) crop with object-position:center 65%, which
   is deliberate for a slab — it pushes the PSA label out of frame. On a raw
   card there is no label to lose, so that same crop eats the card's name. */
.is-raw .card-img, .card-img.is-raw {
    aspect-ratio: 5 / 7;
    object-fit: contain;
    object-position: center;
}

/* ── the rip card ───────────────────────────────────────────────────────────
   The case is part of the CARD, not a wrapper around wherever the card
   happens to be — so it has to survive the hand-off, where the tear engine's
   card element is re-parented out of .pt-root and into the reveal slot
   (_homeFlightCard: slot.appendChild(ptCard)). That move is why this lives
   here and not in pack-tear.js's injected stylesheet: once the card lands, a
   run of `#stage-result .po-card-face.po-slot-hosts-flight ...` rules take it
   over, and an injected rule cannot out-specify an id. Each block below is
   written twice for that reason — once for the flight, once, louder, for the
   landing. They must stay identical. */

.pt-card.pt-raw .pt-face,
#stage-result .po-card-face.po-slot-hosts-flight .pt-card.pt-raw .pt-face {
    --rs-fs: 12px;
    --rs-wl: 11.22%; --rs-wt: 24.57%; --rs-ww: 77.55%; --rs-wh: 64.96%;
    --rs-gap: 1.1cqi;
    container-type: inline-size;
    color: #f5f7f4;
    padding: 0;
    border-radius: 0;
    overflow: visible;
    background: var(--rs-slab, url("/static/img/raw-slab-original.png")) 50% 48.78% / 130.61% 119.07% no-repeat;
    --rs-r: 6.76% / 4.11%;
    border-radius: var(--rs-r);
    filter: none;
    box-shadow:
        0 18px 30px rgba(0,0,0,0.42),
        0 0 46px var(--pt-accent-70, transparent),
        0 0 116px var(--pt-accent-40, transparent);
}
.pt-card.pt-raw .pt-face img,
#stage-result .po-card-face.po-slot-hosts-flight .pt-card.pt-raw .pt-face img {
    position: absolute;
    left: calc(var(--rs-wl) + var(--rs-gap));
    top: calc(var(--rs-wt) + var(--rs-gap));
    width: calc(var(--rs-ww) - 2 * var(--rs-gap));
    height: calc(var(--rs-wh) - 2 * var(--rs-gap));
    max-width: none;
    max-height: none;
    margin: 0;
    object-fit: contain;
    border-radius: 0.9cqi;
    background: transparent;
    box-shadow:
        0 0 0 0.12cqi rgba(0,0,0,0.55),
        0 0.25cqi 0.5cqi rgba(0,0,0,0.55),
        0 0.7cqi 1.4cqi rgba(0,0,0,0.30);
}

/* The slot's OWN case, while a flight card is sitting in it. It stays in the
   DOM because it is what gives the slot its height — the info column's layout
   is measured against that — but it must not paint, or the card is drawn twice,
   slightly out of register. */
#stage-result .po-card-face.po-slot-hosts-flight > .rawshell {
    visibility: hidden;
}

.rawshell,
.ss-rawshell,
[data-celebrate] .ss-card-slab .ss-rawshell,
.pt-card.pt-raw .pt-face,
#stage-result .po-card-face.po-slot-hosts-flight .pt-card.pt-raw .pt-face {
    background-image:
        linear-gradient(90deg, #262728, #242526),
        linear-gradient(180deg,
            rgba(218,232,237,.55) 0%,
            rgba(218,232,237,.55) 2.5%,
            transparent 4%, transparent 19.5%,
            rgba(218,232,237,.55) 21.5%,
            rgba(218,232,237,.55) 100%),
        var(--rs-slab, url("/static/img/raw-slab-original.png"));
    background-size: 67% 2.8%, 100% 100%, 130.61% 119.07%;
    background-position: 31% 17.15%, center, 50% 48.78%;
    background-repeat: no-repeat;
    background-blend-mode: normal, screen, normal;
    border-radius: var(--rs-r);
}

.rawshell,
.pt-card.pt-raw .pt-face,
#stage-result .po-card-face.po-slot-hosts-flight .pt-card.pt-raw .pt-face {
    overflow: hidden;
    isolation: isolate;
}
.pt-card.pt-raw .pt-sheen {
    border-radius: inherit;
    clip-path: inset(0 round 6.76% / 4.11%);
}

.raw-card-image {
    display: inline-block;
    vertical-align: middle;
    flex-shrink: 0;
    height: auto;
    max-width: 100%;
    margin: 0 auto;
}
.rawshell.raw-card-image > img {
    position: absolute !important;
    left: calc(var(--rs-wl) + var(--rs-gap)) !important;
    top: calc(var(--rs-wt) + var(--rs-gap)) !important;
    width: calc(var(--rs-ww) - 2 * var(--rs-gap)) !important;
    height: calc(var(--rs-wh) - 2 * var(--rs-gap)) !important;
    max-width: none !important;
    max-height: none !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    object-fit: contain !important;
    border: 0 !important;
    border-radius: 0.9cqi !important;
    filter: none !important;
    transform: none;
}
#cmFlip.is-raw {
    width: min(320px, 36svh);
    height: auto;
    aspect-ratio: 788 / 1294;
    margin: 0 auto;
    flex: none;
}
/* Each face is a case, so the case turns with the card. */
#cmFlip .pub-modal-flip-face.rawshell {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
}
#cmFlip.is-raw .pub-modal-img { filter: none; border-radius: 0; }
.pub-modal-stage:has(#cmFlip.is-raw) .pub-modal-pedestal { display: none; }
#cardPopupShell { display: contents; }
#cardPopupShell.rawshell { display: block; width: min(85%, 36svh); }
#cardPopupImageWrap.has-raw-card { background: transparent !important; }
#cardScanShell.rawshell { width: min(470px, 45vh); flex: none; }
#cardScanShell.rawshell #cardScanImageWrap { display: block; }
#cardScanShell.rawshell #cardScanImage { width: 100%; height: 100%; max-height: none !important; }
#vlt-card-zoom .rawshell { width: min(440px, 48vh); }
.vlt-slab > .rawshell { width: 100%; max-width: 100%; }
.vlt-slab:has(> .rawshell) { width: 72%; }
.raw-card-image:has(> .pc-dialslab) {
    position: absolute; right: 8%; bottom: 8%; width: 54% !important; z-index: 3;
}
.raw-card-image:has(> .po-slab) {
    position: absolute; right: -18%; bottom: -4%; width: 52% !important;
    transform: rotate(7deg);
}

.sr-card-shape:has(> .rawshell) {
    width:100%;height:auto;aspect-ratio:788 / 1294;
    border:0;background:transparent;overflow:visible;
}
.sr-card-under .sr-card-shape:has(> .rawshell) {
    height:100%;width:auto;aspect-ratio:788 / 1294;
}
.sr-card-shape > .rawshell { display:block; }
.sr-opened-slot > .rawshell { display:block;height:100%;width:auto!important; }

.pub-modal-stage:has(#cmFlip.rawshell) { width:100%; }
.hiw-belt-item:has(> .rawshell) { aspect-ratio:788 / 1294; }
.hiw-vis .hiw-belt-item:first-child .rawshell.raw-card-image > img {
    width:calc(var(--rs-ww) - 2 * var(--rs-gap))!important;
    height:calc(var(--rs-wh) - 2 * var(--rs-gap))!important;
}

/* Mobile, decision screen. The width cap that keeps the card from filling a
   phone is written as `#stage-result .po-card-face > img` — DIRECT child, and
   deliberately so: as a descendant selector its !important declarations also
   hit .pt-face img on the landed flight card and collapsed its picture in one
   frame (see the note on that rule in pack-opening.css). The holder makes the
   image a GRANDCHILD, so the cap stopped reaching it and the card went
   full-bleed.

   Cap the FACE, not the holder inside it. .po-card-face is what the hand-off
   measures to scale the flight card into the slot, so capping only the holder
   would leave the slot full-width and the landed card would go full-bleed
   again a beat later. Same number as the graded cap, so a raw pull takes the
   same footprint on screen as a slab — the card inside ends up a little
   smaller than a slab scan, because the holder's frame and label are part of
   that footprint. The cinematic sizes itself and is not touched. */
@media (max-width: 900px) {
    #stage-result .po-card-face.po-raw {
        width: min(49.5vw, 215px);
        max-width: 100%;
        margin-left: auto;
        margin-right: auto;
    }
}
