/* dressing-room.css: Dressing Room (.dr2-*). */
/* ============================================================
   DRESSING ROOM (.dr2-*)
   The rebuilt room, promoted from its `?v2=1` beta channel. The prefix is historical
   and deliberately kept, exactly as .ib2-* and .sq2-* were on their promotions: one
   contiguous block that never fights the shared .dr-* rules above it in the cascade.
   Every colour is an existing token, so all ten Legacy palettes and both Frontier modes
   come along for free. The coarse-pointer floor sits at the END of this block, per the
   cascade rule the incursion board and squad card already pay for.
   ============================================================ */


/* The live canvas: the pet drawn by the server, every changeable layer drawn here.
   .dr-canvas-frame is already position:relative with aspect-ratio 1/1, so this stack
   fills it and each layer is absolutely placed inside. */
/* overflow: hidden, unlike the sibling .dr-canvas-overlay which is deliberately
   visible so a chip can sit outside the frame. This stack must CLIP, because the
   compositor clips: Wand draws onto a fixed 500x500 canvas, so anything past the edge
   is cropped out of the render. Without this the canvas shows artwork the saved image
   will not contain, and an oversized layer (real ones measure 600x600 and 800x602)
   widens the whole document. */
/* isolation: isolate is load-bearing, not tidiness. `position: absolute` with
   `z-index: auto` does NOT create a stacking context, so without this the stack's own
   layers (z-index 1..N, one per equipped item) compete directly with the drag markers
   in the sibling .dr-canvas-overlay, which sit at z-index 2. On a real 8-item pet a
   layer at z-index 9 painted over every marker and elementFromPoint returned the
   artwork instead of the chip: the canvas rendered perfectly and nothing on it could
   be grabbed, with every server-side test green. Isolating keeps the layer z-indexes
   internal so the later sibling overlay always wins. */
.dr2-canvas-stack { position: absolute; inset: 0; overflow: hidden; isolation: isolate; }
.dr2-layer { position: absolute; }

/* A fixed layer (a vista, or a background whose catalog row pins it) is authored to
   fill the 500x500 canvas exactly, so it is anchored top-left and stretched to the
   frame: the same top-left-at-0,0 convention the compositor uses for these. */
.dr2-layer--body,
.dr2-layer--fixed,
.dr2-layer--backdrop { inset: 0; width: 100%; height: 100%; }
.dr2-layer--body,
.dr2-layer--fixed { object-fit: contain; }

/* A moveable layer is anchored by its CENTRE, matching _composite_apparel_layer's own
   half-width/half-height subtraction, and scaled with the fluid canvas because the
   compositor works at a fixed 500x500 while this frame does not. max-width:none is
   load-bearing: a global img rule would otherwise clamp a large sprite to the frame
   and silently shrink it out of agreement with the render. */
.dr2-layer--moveable {
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    transform: translate(-50%, -50%) scale(var(--dr-canvas-scale, 1));
    transform-origin: center center;
    /* A real <button> for the keyboard, stripped back to bare artwork. It is
       pointer-events: none on purpose: the stack handles pointerdown for the whole
       canvas so it can alpha-hit-test every layer and pick the one actually under the
       cursor. A button can still be tab-focused and key-operated while inert to the
       pointer, which is exactly the split wanted here. */
    padding: 0;
    border: 0;
    background: none;
    pointer-events: none;
    line-height: 0;
}
.dr2-layer--moveable > img { display: block; max-width: none; max-height: none; }
/* Telling one item from another was the weakest part of the canvas: with several
   similarly coloured pieces a dashed box alone does not say WHICH one you grabbed. Three
   signals now, none of them colour alone: a solid ring, a drop shadow that lifts the
   selected art off everything behind it, and (in the markup) the item's name in the
   status line under the canvas. */
.dr2-layer--moveable.is-selected {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
    filter: drop-shadow(0 0 6px var(--color-primary));
}
/* While something IS selected, everything else steps back. This is what actually makes a
   selection legible in a dense stack: the contrast is against the other layers, not
   against the artwork's own colours. */
.dr2-canvas-stack.has-selection .dr2-layer--moveable:not(.is-selected) { opacity: 0.45; }
.dr2-canvas-stack.has-selection .dr2-layer--body { opacity: 0.75; }

/* Hover naming: know WHAT you are about to grab before pressing. With two similar
   pieces stacked, this is the signal that actually answers "which one is this"; the
   selection dimming only helps once you have already committed to one. Dotted, so it
   never reads as the solid selection ring. */
.dr2-layer--moveable.is-hovered { outline: 2px dotted var(--color-primary); outline-offset: 2px; }

/* Ghost-while-dragging (opt-in, dressingView.ghostDrag): the dragged layer's own pixels
   are hidden and a solid-colour silhouette is painted in their exact shape via a CSS mask
   built from the artwork's own alpha channel (its `src`, read into --dr2-ghost-src at
   pointerdown). This is the one thing dimming everything ELSE (has-selection above)
   cannot fix: a full-canvas atmosphere piece is still opaque while it is the thing being
   dragged, so it blacks out the pet and every other item right under the player's own
   cursor. Masking, not just fading the opacity of the real art, because a large sprite is
   often mostly transparent margin around a small shape; fading its opacity leaves the
   same blocked rectangle, only fainter. -webkit- prefix for Safari, which has no
   unprefixed mask-image. */
.dr2-layer--moveable.is-drag-ghost {
    background-color: var(--color-primary);
    -webkit-mask-image: var(--dr2-ghost-src, none);
    mask-image: var(--dr2-ghost-src, none);
    -webkit-mask-size: 100% 100%;
    mask-size: 100% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    opacity: 0.55;
}
.dr2-layer--moveable.is-drag-ghost > img { opacity: 0; }

/* Depth pill: bring-to-front / send-to-back, floating on the selected art. A sibling of
   the live-canvas stack (never inside it), with pointer-events on so its buttons work while
   the stack around it stays the drag surface. Anchored above the item's centre. */
.dr-depth-pill {
    position: absolute;
    transform: translate(-50%, -118%);
    display: flex;
    gap: 2px;
    padding: 3px;
    border-radius: var(--radius-pill);
    background: var(--bg-elevated);
    border: 1px solid var(--color-primary);
    box-shadow: var(--shadow-md);
    z-index: 6;
    pointer-events: auto;
}
.dr-depth-pill__btn {
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-primary);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
}
@media (hover: hover) { .dr-depth-pill__btn:hover { background: var(--bg-hover); color: var(--color-primary); } }
.dr-depth-pill__btn:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
/* The pill's third button (Isolate) toggles dressingView.solo, same active signal as the
   layer-list row's own ◉ button: filled background, not colour alone. Shaped as a label
   pill rather than the 30px circle its front/back siblings use: a bare "◉" explains
   nothing on its own, so this one carries a real word (via x-text) and needs auto width
   and left-aligned content to fit it, not the circle's fixed square + centred glyph. */
.dr-depth-pill__btn--label {
    display: flex;
    align-items: center;
    justify-content: center;
    width: auto;
    height: 26px;
    border-radius: var(--radius-pill);
    padding: 0 10px;
    gap: 4px;
    font-size: 0.78rem;
    white-space: nowrap;
}
.dr-depth-pill__btn.is-active { background: var(--color-primary); color: var(--text-inverse); }
@media (pointer: coarse) {
    .dr-depth-pill__btn { width: 44px; height: 44px; }
    /* The label variant stays auto-width even on a coarse pointer: forcing it square
       would either clip "Isolate"/"Only this" or force the pill to wrap. A 44px MIN
       height (not a fixed square) still meets the touch-target floor. */
    .dr-depth-pill__btn--label { width: auto; height: 44px; padding: 0 14px; }
}

/* A locked layer is not draggable and says so. */
.dr2-layer--moveable.is-locked { cursor: not-allowed; }
.dr2-layer-view__btn.is-locked { color: var(--color-warning, var(--text-muted)); }
.dr2-layer--moveable:focus-visible {
    outline: 3px solid var(--color-primary);
    outline-offset: 2px;
}

/* touch-action: none, or the browser's own pan gesture wins and a touch drag scrolls
   the page instead of moving the layer: the same reason .dr-chip needs it. */
.dr2-canvas-stack[data-live-canvas] { cursor: grab; touch-action: none; }
.dr2-canvas-stack[data-live-canvas]:active { cursor: grabbing; }

.dr2-guide {
    position: absolute;
    z-index: 999;
    pointer-events: none;
    background: var(--color-primary);
    opacity: 0.75;
}
.dr2-guide--x { top: 0; bottom: 0; width: 1px; transform: translateX(-0.5px); }
.dr2-guide--y { left: 0; right: 0; height: 1px; transform: translateY(-0.5px); }
.dr2-guide[hidden] { display: none; }

/* The baked render, demoted from "the thing you wait for" to "the picture other pages
   use". Its own <img> is 500px intrinsic, so it needs the same fluid clamp the live
   frame gives the canvas. */
.dr2-saved-render { margin-top: 12px; }
.dr2-saved-render > summary {
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--text-muted);
    padding: 6px 0;
}
.dr2-saved-render > summary:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.dr2-saved-render img { max-width: 100%; height: auto; }

@media (pointer: coarse) {
    .dr2-saved-render > summary { min-height: 44px; display: flex; align-items: center; }
}

/* Reduced motion: the guides are static rules, but keep the grab cursor honest. */
body.reduced-motion .dr2-layer--moveable { transition-duration: 0.001s; }

@media (pointer: coarse) {
    /* A coarse pointer cannot aim at a few transparent pixels, so give the artwork a
       little forgiveness by widening the selected outline rather than the hit area
       (widening the box would break the alpha hit test the canvas depends on). */
    .dr2-layer--moveable.is-selected { outline-width: 3px; outline-offset: 3px; }
    /* Touch: only the SELECTED item's handle takes the finger. Nine 44px handles on a
       310px phone canvas overlap one another, so a tap landed on whichever handle
       happened to be on top. Unselected items are picked by tapping their art (which
       cycles through a stack) or their row in the Layers tab; the selected item keeps
       a guaranteed grab point, which is what the handle is for. */
    .dr-chip--handle:not(.is-selected) { pointer-events: none; }
}

/* Transform controls on a v2 layer row. Wraps to its own line under the item's name
   and position actions, because a range input needs real width to be usable and a
   cramped one is worse than none. */
.dr2-transform {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    width: 100%;
    max-width: none;
    margin: 6px 0 0;
}
/* Grid, not flex: the row is label | slider | readout, and a 1fr middle track fills the
   space reliably. flex-grow on an <input type=range> did not: the UA gives it an
   intrinsic size that survived both `flex: 1 1 auto` and `flex: 1 1 0`, so the track
   stayed at its floor with 272px of the row sitting unused beside it. */
.dr2-transform__control {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 6px;
    font-size: 0.8rem;
    color: var(--text-muted);
}
/* One control per line at EVERY width, and the slider takes the room that leaves.
   A fixed 96px track carried the whole 0.25x-3x range in 55 steps of 1.7px each, so a
   single pixel of pointer travel jumped the size by about 5% and placing anything
   deliberately was impossible: reported from real play as "it goes up or down 10%".
   This used to be corrected below 768px only, which left the desktop slider, the one
   most likely to be used for fine work, as the worst of the three. */
.dr2-transform__control { width: 100%; }
.dr2-transform__control > input[type="range"] { width: 100%; min-width: 0; }
.dr2-transform__control > output { min-width: 3.5em; font-variant-numeric: tabular-nums; }
/* The mirror checkbox is a two-part row, not three, so it opts out of the grid.
   flex: 0 0 auto because the wrapping .dr2-transform above was shrinking it below its own
   content: measured 37px wide holding a 13px box plus the word "Mirror", i.e. the box and
   the label were overlapping. min-height gives the whole label a real touch target, since
   a 13px UA checkbox is nowhere near the coarse-pointer floor and the label is what a
   finger actually lands on. */
.dr2-transform__control--flip {
    display: flex;
    /* flex-direction is load-bearing: there is a global `label { display: flex;
       flex-direction: column }` in this file, so a label that only says `display: flex`
       inherits COLUMN and stacks its own checkbox above its own text. That is what made
       the Mirror control 37px wide and 54px tall with the box sitting over the word. */
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    flex: 0 0 max-content;
    gap: 6px;
    width: auto;
    min-width: max-content;
    min-height: 44px;
}

@media (width < 768px) {
    .dr2-transform { gap: 8px; }
}

@media (pointer: coarse) {
    .dr2-transform__control > input[type="range"] { min-height: 44px; }
    /* A 13px UA checkbox is the smallest target on the page by a wide margin. */
    .dr2-transform__control--flip input[type="checkbox"] { width: 22px; height: 22px; }
    .dr2-transform__control--flip { min-height: 44px; }
}

/* ---- v2 layout: stage + tray --------------------------------------------
   One markup path. STAGE (the pet, its bar, the Inspector) and TRAY (Layers, Wear,
   Scenery, Looks as tabs) sit side by side from 768px and stack below it.

   Phone: only .dr2-stage is pinned. The whole canvas column used to be sticky, and with
   its help, view buttons and status lines it measured 696px on an 812px screen, so the
   layer list and shelf scrolled underneath it and could not really be reached. The column
   and the Alpine root inside it become `display: contents` so .dr2-stage is a grid item
   of .dr2-layout itself: a sticky element only sticks within its parent, and its parent
   is now the whole room rather than a column that ends right under the canvas. The frame
   is capped at 40dvh (dvh: a phone's address bar makes vh taller than what is visible),
   which with the bar leaves the tray roughly a third of the screen at all times.

   Tablet and up: the tray is height-capped to the viewport and scrolls inside itself, so
   the pet and whatever is being picked are always on screen together. The stage is not
   sticky there: it is never taller than the tray's cap in practice, and a sticky column
   taller than the viewport hides its own bottom until the page ends. */
.dr2-layout { display: grid; gap: 14px; }
.dr2-stage-col, .dr2-tray-col { min-width: 0; }
.dr2-stage { min-width: 0; }

@media (width < 768px) {
    .dr2-stage-col,
    .dr2-stage-col > .dr-canvas { display: contents; }
    .dr2-stage {
        position: sticky;
        top: var(--header-height);
        z-index: 3;
        margin: 0 -12px;
        padding: 6px 12px 4px;
        background: var(--bg-surface);
        border-bottom: 1px solid var(--border-subtle);
    }
    .dr2-stage .dr-canvas-frame { max-width: min(100%, 40dvh); }
    /* The panel's 20px padding left a 294px canvas on a 375px phone. */
    .dr2-panel-root { padding: 12px; }
}

@media (width >= 768px) {
    /* minmax(0, ...) on both tracks, never a bare 1fr or auto: min-content would leak
       out and widen the document (the saved-render image is 500px intrinsic). */
    .dr2-layout {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        align-items: start;
        gap: 18px;
    }
    .dr2-stage .dr-canvas-frame { max-width: 480px; }
    .dr2-tray-col .dr2-workbench {
        display: flex;
        flex-direction: column;
        max-height: calc(100dvh - var(--header-height) - 32px);
    }
    .dr2-tray-col .dr2-tabs { flex: none; }
    /* position: relative makes this scroll box the containing block for absolutely
       positioned descendants (an .sr-only legend deep in the Scene shelf). Without it they
       resolve against the page, escape the clip, and stretch the document by thousands of
       pixels; every whole-panel swap then snaps the scroll position up. */
    .dr2-tray-col .dr2-panel {
        position: relative;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding-right: 4px;
    }
}
/* Below 1024px the app shows the bottom tab bar, which the tray's cap must clear too. */
@media (768px <= width < 1024px) {
    .dr2-tray-col .dr2-workbench {
        max-height: calc(100dvh - var(--header-height) - var(--tabbar-height) - 32px);
    }
}
@media (width >= 1280px) {
    .dr2-layout { grid-template-columns: minmax(0, 480px) minmax(0, 1fr); }
}

/* The stage bar: Undo, Redo, the status line and Tools on one row under the canvas. */
.dr2-stagebar {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    min-width: 0;
}
.dr2-stagebar .btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.dr2-stagebar__status {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    padding: 0 4px;
    font-size: 0.8rem;
}
/* On a phone the bar's buttons drop their words (each keeps an aria-label) so the status
   line gets the room: it is the only on-screen account of what is selected, and squeezed
   to "Tap an ite…" it said nothing. Two lines at most, then an ellipsis. */
@media (width < 768px) {
    .dr2-stagebar { gap: 4px; }
    .dr2-stagebar > .btn,
    .dr2-tools__toggle { min-width: 44px; justify-content: center; padding-left: 8px; padding-right: 8px; }
    .dr2-stagebar__word { display: none; }
    .dr2-stagebar__status {
        font-size: 0.78rem;
        line-height: 1.3;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
}
/* Beside the tray the stage column is ~300-480px wide, too narrow to share a row with the
   status sentence, so the sentence takes its own line under the buttons. */
@media (width >= 768px) {
    .dr2-stagebar { flex-wrap: wrap; }
    .dr2-stagebar__status { order: 1; flex-basis: 100%; padding: 2px 0 0; }
    .dr2-tools { margin-left: auto; }
}
.dr2-stage__note { margin: 4px 0 0; }

/* Tools: a popover that opens UP over the canvas, so it never grows the pinned stage. */
.dr2-tools { position: relative; flex: none; }
.dr2-tools__toggle.is-active { color: var(--color-primary); border-color: var(--color-primary); }
.dr2-tools__menu {
    position: absolute;
    right: 0;
    bottom: calc(100% + 6px);
    z-index: 8;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    width: min(300px, calc(100vw - 32px));
    max-height: min(60dvh, 420px);
    overflow-y: auto;
    padding: 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
    box-shadow: var(--shadow-md);
}
.dr2-tools__menu .btn { justify-content: flex-start; width: 100%; }
.dr2-tools__menu .dr-inline-form { display: block; width: 100%; max-width: none; margin: 0; }
.dr2-tools__menu .dr2-viewbar__note { margin: 0; }
.dr2-tools__menu .btn.is-active { color: var(--color-primary); border-color: var(--color-primary); }

/* Belladonna, compact on a phone: one row, her line clamped to two lines. Nothing
   load-bearing lives in her line (it is random per render), so clamping costs nothing. */
@media (width < 768px) {
    .dr2-host { padding: 4px 8px; margin-bottom: 8px; gap: 8px; }
    .dr2-host .persona-surface__portrait,
    .dr2-host__portrait,
    .dr2-host__placeholder { width: 32px; height: 32px; font-size: 1.05em; }
    .dr2-host__name { display: none; }
    .dr2-host__line {
        font-size: 0.82rem;
        line-height: 1.3;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
    .dr2-panel-root > .panel__header { margin-bottom: 8px; }
}

/* The Inspector. Inline under the canvas from 768px. On a phone it is a bottom sheet over
   the tray, shown only while the player has an item selected, because inline it would sit
   in the flow between the pinned stage and the tray, i.e. behind the stage as soon as the
   player scrolled to a layer row. It clears the app's bottom tab bar. */
@media (width < 768px) {
    .dr2-inspector { display: none; }
    .dr2-inspector.is-open {
        display: block;
        position: fixed;
        left: 0;
        right: 0;
        bottom: calc(var(--tabbar-height) + env(safe-area-inset-bottom, 0px));
        /* Above the Campfire dock button (9990), which otherwise floats over the sheet's
           bottom-right corner, i.e. over Center. Still below the notification panel
           (9996) and toasts (9999). */
        z-index: 9991;
        max-height: 46dvh;
        overflow-y: auto;
        overscroll-behavior: contain;
        margin: 0;
        padding: 8px 14px 10px;
        border-top: 1px solid var(--color-primary);
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        background: var(--bg-elevated);
        box-shadow: 0 -10px 28px -14px rgba(0, 0, 0, 0.6);
    }
    .dr2-inspector.is-open .dr2-inspector__empty { display: none !important; }
    /* Three rows, not four: head, then each slider, then Mirror | Reset Center on one
       line. Stacked, Mirror sat alone on its own centred row and the sheet measured 245px
       for three controls. The transform form is display: contents so its controls become
       grid cells beside the separate Reset/Center forms; it still submits and still
       receives the slider input events, which bubble through it as before. */
    .dr2-inspector.is-open .dr2-inspector__panel {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        align-items: center;
        gap: 4px 8px;
    }
    .dr2-inspector.is-open .dr2-inspector__head,
    .dr2-inspector.is-open .dr2-transform__control:not(.dr2-transform__control--flip) { grid-column: 1 / -1; }
    .dr2-inspector.is-open .dr2-transform { display: contents; }
    .dr2-inspector.is-open .dr2-transform__control { min-height: 40px; }
    .dr2-inspector.is-open .dr2-transform__control--flip { grid-column: 1; justify-self: start; }
    .dr2-inspector.is-open .dr-layer-card__position-actions {
        grid-column: 2;
        justify-self: end;
        width: auto;
        flex-wrap: nowrap;
        gap: 6px;
    }
    .dr2-inspector.is-open .dr2-inspector__head { min-height: 44px; gap: 6px; }
    .dr2-inspector.is-open .dr2-inspector__depth { font-size: 0.72rem; }
}
.dr2-inspector__done { margin-left: auto; }

/* ---- workbench (the tray) ---- */
.dr2-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.dr2-tab__short { display: none; }
.dr2-tab__count {
    display: inline-block;
    min-width: 1.5em;
    padding: 0 5px;
    border-radius: var(--radius-pill);
    background: var(--bg-hover);
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
}
/* The base tab; the phone and narrow-tray rules below must come after it to win. */
.dr2-tab {
    padding: 8px 14px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-color);
    background: var(--bg-subtle);
    color: var(--text-secondary);
    font-size: 0.9rem;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
/* A phone shows the short labels in one row, however many tabs there are (four, or five
   with the Design tab): two rows under the pinned stage left no room for the tray. The
   full label stays in the accessibility tree (visually hidden, not display:none) so it is
   still each tab's name. */
@media (width < 768px) {
    .dr2-tabs {
        display: grid;
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
        gap: 4px;
        margin-bottom: 10px;
    }
    .dr2-tab { width: 100%; padding: 8px 2px; text-align: center; font-size: 0.82rem; }
    .dr2-tab__short { display: inline; }
    /* Pinned directly under the pinned stage (whose height apparelDressingRoom
       publishes), so switching tabs never means scrolling back up past a shelf. */
    .dr2-tray-col .dr2-tabs {
        position: sticky;
        top: calc(var(--header-height) + var(--dr2-stage-h, 0px));
        z-index: 2;
        margin: 0 -12px 10px;
        padding: 6px 12px;
        background: var(--bg-surface);
        border-bottom: 1px solid var(--border-subtle);
    }
    .dr2-tab__long {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
    }
}
/* Beside the canvas the tray's width depends on the shell (the sidebar, the Classic desk)
   more than on the viewport: measured at 354px on a 1440px Classic window, where the four
   full labels wrapped onto two rows. So the switch to short labels keys off the tray's
   own width. */
.dr2-tray-col { container: dr2-tray / inline-size; }
@container dr2-tray (width < 560px) {
    .dr2-tabs { flex-wrap: nowrap; gap: 4px; }
    .dr2-tab { flex: 1 1 auto; padding: 8px 6px; text-align: center; font-size: 0.85rem; white-space: nowrap; }
    .dr2-tab__short { display: inline; }
    .dr2-tab__long {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
    }
}
@media (hover: hover) { .dr2-tab:hover { color: var(--text-primary); border-color: var(--color-primary); } }
.dr2-tab[aria-selected="true"] { color: var(--color-primary); border-color: var(--color-primary); background: var(--bg-hover); }
.dr2-tab:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

.dr2-filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 12px; }
.dr2-filters__search { flex: 1 1 180px; }
.dr2-filters__search input { width: 100%; }
.dr2-chipbar { display: flex; flex-wrap: wrap; gap: 4px; }
.dr2-chip {
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-color);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.78rem;
    cursor: pointer;
}
.dr2-chip.is-active { color: var(--color-primary); border-color: var(--color-primary); background: var(--bg-hover); }
.dr2-chip:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

.dr2-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px; }
/* Measured at 285px tall for 64px of art: five stacked rows, of which the name alone
   took 50px by wrapping. The art is the thing being chosen, so it grew and everything
   else tightened around it. */
.dr2-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    text-align: center;
    padding: 10px 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-subtle);
}
.dr2-card.is-equipped { border-color: var(--color-primary); background: var(--bg-hover); }
.dr2-card form { width: 100%; max-width: none; margin: 0; }
.dr2-card__art {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 76px;
    height: 76px;
    border-radius: var(--radius-md);
    background: var(--bg-hover);
    font-size: 1.8em;
}
.dr2-card__art img { width: 100%; height: 100%; }
.dr2-card__art img { border-radius: var(--radius-md); object-fit: cover; }
/* Two lines maximum, then ellipsis. An item called "Starforged Antler Crown" otherwise
   sets the height of every card in its row. */
.dr2-card__name {
    font-weight: 600;
    margin: 0;
    font-size: 0.85rem;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.dr2-card .rarity-chip { font-size: 0.68rem; }
.dr2-card .state-chip { font-size: 0.7rem; }
.dr2-card__note { margin: 0; font-size: 0.75rem; color: var(--text-muted); }

.dr2-subhead { margin: 18px 0 8px; font-size: 0.95rem; }
.dr2-scene-extras > .dr2-subhead:first-child { margin-top: 0; }
.dr2-empty { text-align: center; padding: 32px 16px; color: var(--text-muted); }
.dr2-empty__icon { font-size: 2.2em; margin: 0 0 8px; opacity: 0.6; }
.dr2-empty p { margin: 0; }
.dr2-empty__actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin-top: 12px !important; }
.dr2-empty-filter { margin: 12px 0 0; color: var(--text-muted); font-size: 0.85rem; }

@media (pointer: coarse) {
    .dr2-tab { min-height: 44px; }
    .dr2-chip { min-height: 44px; display: flex; align-items: center; }
}

/* ---- v2 hub: get the pet onto the first screen -------------------------- */
.dr2-hub-head {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}
.dr2-hub-head__titles { min-width: 0; }
.dr2-hub-head__titles .page-title { margin: 0; }
.dr2-hub-head__actions { display: flex; flex-wrap: wrap; gap: 8px; }

.dr2-hub { margin-bottom: 14px; }

/* Phone, with a companion chosen: head and picker share one row (chip | 🎒 | 🛒). The
   chip already shows the companion's portrait and name, so the h1 is visually hidden
   rather than removed, and the link words are visually hidden so each link keeps its
   accessible name. Nothing chosen yet keeps the full stacked head: then the picker IS
   the page. */
@media (width < 768px) {
    .dr2-top--selected {
        position: relative;  /* containing block for the visually-hidden title and labels */
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: start;
        gap: 8px;
        margin-bottom: 10px;
    }
    .dr2-top--selected .dr2-hub-head { display: contents; }
    .dr2-top--selected .dr2-hub-head__titles {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
    }
    .dr2-top--selected .dr2-hub-head__actions { grid-column: 2; grid-row: 1; flex-wrap: nowrap; gap: 6px; }
    .dr2-top--selected .dr2-hub { grid-column: 1; grid-row: 1; margin: 0; min-width: 0; }
    .dr2-top--selected .dr2-hub-head__label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
    }
    .dr2-top--selected .dr2-hub-head__actions .btn { min-width: 44px; min-height: 44px; justify-content: center; padding: 0 10px; }
    .dr2-top--selected .dr2-picker-compact__btn { max-width: none; }
}
.dr2-picker { display: flex; flex-direction: column; gap: 8px; }
.dr2-picker__search input { width: 100%; max-width: 320px; }

/* The collapsed picker: a single-row "who's in the chair" chip, so the ~140px strip
   below only costs its space while a player is actually choosing a companion. */
.dr2-picker-compact__btn {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    max-width: 320px;
    padding: 6px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-subtle);
    cursor: pointer;
    text-align: left;
    min-height: 44px;
}
@media (hover: hover) { .dr2-picker-compact__btn:hover { border-color: var(--color-primary); } }
.dr2-picker-compact__btn:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.dr2-picker-compact__art {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-hover);
}
.dr2-picker-compact__art img { width: 100%; height: 100%; object-fit: cover; }
.dr2-picker-compact__name { flex: 1 1 auto; min-width: 0; font-weight: 600; font-size: 0.88rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dr2-picker-compact__switch { flex: 0 0 auto; font-size: 0.78rem; color: var(--text-muted); }

/* A single scrolling row, not a wrapping grid: the picker must stay a fixed, small
   height whatever the roster size, or a large crew pushes the canvas off the screen
   again, which is the whole problem this rebuild exists to fix. */
.dr2-picker__strip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 6px;
    scrollbar-width: thin;
}
.dr2-pet {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    width: 78px;
    padding: 6px 4px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-subtle);
    cursor: pointer;
    text-align: center;
}
.dr2-pet.is-selected { border-color: var(--color-primary); background: var(--bg-hover); }
.dr2-pet:has(input:focus-visible) { outline: 2px solid var(--color-primary); outline-offset: 2px; }
@media (hover: hover) { .dr2-pet:hover { border-color: var(--color-primary); } }
.dr2-pet__art {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-hover);
}
.dr2-pet__art img { width: 100%; height: 100%; object-fit: cover; }
.dr2-pet__name {
    font-size: 0.75rem;
    font-weight: 600;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dr2-pet__species { font-size: 0.68rem; color: var(--text-muted); }

@media (pointer: coarse) {
    .dr2-pet { width: 84px; }
}

/* Wardrobe collection figure. A number and a bar, not a catalogue: see the v2 wardrobe
   template for why un-owned pieces are not shown here. */
.dr2-collection {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin: 0 0 14px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-subtle);
}
.dr2-collection__count { margin: 0; font-size: 0.9rem; }
.dr2-collection__bar {
    flex: 1 1 140px;
    min-width: 120px;
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--bg-hover);
    overflow: hidden;
}
.dr2-collection__bar > span { display: block; height: 100%; background: var(--color-primary); }

/* Wardrobe on a phone: the four filters stacked full width put ~330px of form between the
   header and the first item. Search keeps the full row; the three selects share one. */
@media (width < 768px) {
    .wardrobe-filters { padding: 10px; }
    .wardrobe-filters__controls {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 8px;
    }
    .wardrobe-filters__controls > label:first-child { grid-column: 1 / -1; }
    .wardrobe-filters__controls label { font-size: 0.78rem; }
    .wardrobe-item { gap: 10px; padding: 10px; }
    .wardrobe-item__art { width: 48px; height: 48px; }
    .wardrobe-item__body p { margin-top: 2px; margin-bottom: 2px; }
}

/* ---- the room's host, and the fitting-room framing --------------------------
   Belladonna has no portrait yet, so this has to work as a compact name-and-line strip
   first and gain a picture later without moving anything. Deliberately small: she is an
   accent, and the pet is the subject. */
.dr2-host {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 12px;
    padding: 8px 10px;
    border-left: 3px solid var(--color-violet, var(--color-primary));
    border-radius: var(--radius-sm);
    background: var(--bg-subtle);
}
/* The shared partial also carries its own .persona-surface* classes, which are sized
   for a full mentor plate (Crafting, the Handbook). Reset them inside this strip rather
   than forking the partial: she is an accent here, not the subject. */
.dr2-host .persona-surface,
.dr2-host__persona { display: flex; align-items: center; gap: 10px; width: 100%; margin: 0; padding: 0; border: 0; background: none; }
.dr2-host .persona-surface__portrait { flex: 0 0 auto; width: 44px; height: 44px; margin: 0; padding: 0; border: 0; background: none; }
.dr2-host .persona-surface__body,
.dr2-host__body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.dr2-host__portrait,
.dr2-host__placeholder {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    object-fit: cover;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-hover);
    font-size: 1.3em;
}
.dr2-host__name { font-size: 0.78rem; color: var(--text-muted); }
.dr2-host__line { margin: 0; font-size: 0.9rem; font-style: italic; color: var(--text-secondary); }

/* The layer stack read as a garment rail. This is where the backstage framing actually
   lives: not in the host's portrait, which does not exist yet, but in the shape of the
   controls. A hanging rail above the cards, and each card hanging from it. */

/* The Inspector: size / turn / mirror / reset / center for the selected layer, one block
   shown at a time. Inline under the stage from 768px (see the phone sheet above). */
.dr2-inspector { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border-color); }
.dr2-inspector__empty { color: var(--text-muted); font-size: var(--font-size-sm); margin: 0; }
.dr2-inspector__panel { display: flex; flex-direction: column; gap: 12px; }
.dr2-inspector__head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dr2-inspector__head .dr-layer-card__thumb { border-radius: var(--radius-sm); object-fit: cover; }
.dr2-inspector__name { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dr2-inspector__depth { font-size: 0.78rem; color: var(--text-muted); white-space: nowrap; }

.dr2-panel .dr-layers { position: relative; padding-top: 10px; }
.dr2-panel .dr-layers::before {
    content: "";
    position: absolute;
    top: 3px;
    left: 6px;
    right: 6px;
    height: 2px;
    border-radius: 2px;
    background: var(--border-color);
}

/* The canvas as a lit vanity: a soft pool of light behind the pet rather than a plain
   box. One inset ring in existing tokens, so every palette and both Frontier modes get it
   for free. */
.dr2-stage .dr-canvas-frame {
    border-radius: var(--radius-md);
    box-shadow: inset 0 0 0 1px var(--border-color),
                0 0 34px -12px color-mix(in srgb, var(--color-primary) 45%, transparent);
}

/* ---- view-only visibility: hide / solo / hide-all ------------------------
   None of this changes the pet or the saved picture. Opacity rather than display:none on
   the canvas, so a hidden layer keeps its box and the layout underneath cannot shift as
   things are toggled; pointer-events off, so a hidden layer cannot be grabbed by a drag
   the player can no longer see. */
.dr2-layer.is-view-hidden { opacity: 0; pointer-events: none; }
/* Same specificity as .has-selection's own dimming rule above (4 classes each), so this
   wins purely on being later in the file: hiding or soloing a layer is a deliberate
   "make it actually gone" action, and it must win over the passive "everything else steps
   back a little" dimming a selection triggers. Without this, isolating anything while a
   DIFFERENT layer is selected left the hidden layer sitting at the ordinary 0.45 dim
   instead of 0: exactly the state a player reaches for isolate to escape in the first
   place, since selecting the item you want to isolate is the natural first step before
   pressing the row's own ◉/the depth pill's Isolate button. */
.dr2-canvas-stack.has-selection .dr2-layer--moveable.is-view-hidden { opacity: 0; }

.dr2-viewbar__note { margin: 6px 0 0; font-size: 0.8rem; color: var(--text-muted); }
.dr2-viewbar__error { margin: 6px 0 0; font-size: 0.82rem; color: var(--color-warning, var(--text-primary)); }

/* A layer row: grip, thumb, name, eye, ⋯ on one line; the ⋯ opens .dr2-layer-more as a
   full-width second line of labelled actions. One behaviour for every pointer and width:
   inline, the full set wrapped unpredictably in any tray narrower than ~460px, which is
   every tray this room has (a phone, a tablet column, a Classic-shell desktop). */
.dr2-layer-more-toggle { flex: none; }
.dr-layer-card.is-more-open .dr2-layer-more-toggle { color: var(--color-primary); border-color: var(--color-primary); }
.dr2-layer-more { display: none; flex: 0 0 100%; flex-wrap: wrap; align-items: center; gap: 6px; padding-top: 4px; }
.dr-layer-card.is-more-open .dr2-layer-more { display: flex; }
.dr2-layer-more .reorder-nudge { display: contents; }
.dr2-layer-more .dr-inline-form { display: contents; }
.dr2-layer-more .reorder-nudge__btn,
.dr2-layer-more .dr2-layer-view__btn {
    width: auto;
    height: 32px;
    gap: 2px;
    padding: 0 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-pill);
    background: var(--bg-surface);
    color: var(--text-secondary);
    font-size: 0.8rem;
}
.dr2-layer-more .dr2-layer-view__btn.is-active { color: var(--color-primary); border-color: var(--color-primary); }
.dr2-layer-more .dr2-layer-view__btn.is-locked { color: var(--color-warning, var(--text-primary)); }
.dr2-layer-more .dr-layer-card__unequip { margin-left: auto; }
.dr2-layer-view__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text-muted);
    font-size: 0.85rem;
    cursor: pointer;
}
@media (hover: hover) { .dr2-layer-view__btn:hover { border-color: var(--border-color); color: var(--text-primary); } }
.dr2-layer-view__btn.is-off { color: var(--color-warning, var(--text-muted)); }
.dr2-layer-view__btn.is-active { color: var(--color-primary); border-color: var(--color-primary); }
.dr2-layer-view__btn:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

@media (pointer: coarse) {
    .dr2-layer-view__btn { width: 44px; height: 44px; }
    /* After the generic 44px square above: the overflow row's buttons carry a word, so
       they keep their auto width and only take the height floor. */
    .dr2-layer-more .reorder-nudge__btn,
    .dr2-layer-more .dr2-layer-view__btn { width: auto; min-width: 44px; height: 44px; }
}

/* ---- try-it-on --------------------------------------------------------------
   The preview must never be mistakable for something equipped, so it is marked three
   ways: reduced opacity, a dashed outline, and (in the markup) a status line and a
   per-card label. Never colour alone. */
/* Natural size, scaled with the canvas, exactly like a real moveable layer: this
   previously used inset:0 + 100% + object-fit, which blew an 18x89 sprite up to fill the
   whole 500x500 frame. A try-on has to show the piece at the size it would actually be. */
.dr2-layer--tryon {
    left: 50%;
    top: 50%;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    transform: translate(-50%, -50%) scale(var(--dr-canvas-scale, 1));
    transform-origin: center center;
    z-index: 900;
    opacity: 0.7;
    outline: 2px dashed var(--color-warning, var(--color-primary));
    outline-offset: -4px;
    pointer-events: none;
}
.dr2-tryon { margin-top: 18px; padding-top: 12px; border-top: 1px dashed var(--border-color); }
.dr2-tryon__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.dr2-tryon__head .dr2-subhead { margin: 0; }
.dr2-tryon__note { margin: 6px 0 10px; font-size: 0.82rem; color: var(--text-muted); }
.dr2-tryon .btn.is-active { color: var(--color-primary); border-color: var(--color-primary); }
/* The preview is draggable, so it needs to look grabbable. It is still pointer-events:
   none as an element; the stack recognises a press over its opaque pixels, the same way
   it does for real layers. */
.dr2-canvas-stack:has(.dr2-layer--tryon:not([style*="display: none"])) { cursor: grab; }
.dr2-card--tryon { border-style: dashed; }
.dr2-card--tryon.is-previewing { border-color: var(--color-warning, var(--color-primary)); border-style: solid; }

/* Phone: tighten the band above the canvas. The header, picker, panel heading and host
   line together put the pet 599px down an 812px screen, so a page whose whole point is
   looking at your companion showed about two thirds of one. Nothing is removed here,
   only sized down: the species label goes because it is already on the card art and
   repeated in the panel below. */
@media (width < 480px) {
    .dr2-pet { width: 64px; }
    .dr2-pet__art { width: 44px; height: 44px; }
    .dr2-pet__species { display: none; }
}

/* A narrow tray (a phone, or the tablet column) fits three cards a row instead of two,
   with the art still the largest thing on the card. Measured on a 375px phone: two cards
   of ~240px a row meant the shelf showed one row at a time under the pinned canvas. */
@container dr2-tray (width < 440px) {
    /* Search and the type chips share one row; the chips scroll sideways rather than
       wrapping into a second 44px row above the shelf. */
    .dr2-filters { flex-wrap: nowrap; gap: 6px; }
    .dr2-filters__search { flex: 1 1 110px; min-width: 0; }
    .dr2-chipbar { flex: 0 1 auto; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
    .dr2-chip { flex: none; }
    .dr2-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 6px; }
    .dr2-card { padding: 6px 5px 8px; gap: 2px; }
    .dr2-card__art { width: 60px; height: 60px; }
    .dr2-card__name { font-size: 0.78rem; }
    .dr2-card__meta { font-size: 0.7rem; gap: 2px 4px; }
    .dr2-card .rarity-chip { font-size: 0.62rem; padding: 1px 5px; }
    .dr2-card__note { font-size: 0.7rem; }
    .dr2-card .btn { width: 100%; padding-left: 4px; padding-right: 4px; }
}

/* Rarity + stock on one line inside an item card. */
.dr2-card__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 4px 6px;
    margin: 0;
    font-size: var(--font-size-xs);
}


/* The canvas help disclosure. Styled as quiet text rather than a panel: it sits
   directly under the pet and a bordered box there reads as another control. */
.dr2-help { margin: 6px 0 0; font-size: var(--font-size-sm); }
.dr2-help > summary {
    cursor: pointer;
    color: var(--text-muted);
    padding: 4px 0;
    list-style: none;
}
.dr2-help > summary::-webkit-details-marker { display: none; }
.dr2-help > summary::before { content: '▸ '; }
.dr2-help[open] > summary::before { content: '▾ '; }
@media (hover: hover) {
    .dr2-help > summary:hover { color: var(--text-secondary); }
}
.dr2-help > summary:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}
.dr2-help__body {
    display: grid;
    gap: 4px;
    padding: 6px 0 0 10px;
    border-left: 2px solid var(--border-subtle);
    margin-left: 2px;
}
.dr2-help__body p { margin: 0; color: var(--text-secondary); }
.dr2-help__body strong { color: var(--text-primary); }

/* The backdrop's layer-stack swatch. A <span>, not an <img>, because a backdrop is
   painted rather than loaded, so .dr-layer-card__thumb's object-fit has nothing to act
   on and the box needs its own size. */
.dr2-backdrop-swatch {
    display: block;
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
}

/* Coarse-pointer floor for the controls added in the design pass. These are all btn-xs,
   whose own min-height is declared further down the file at the same specificity, so this
   block has to sit at the END of the .dr2-* run or it loses the cascade and silently does
   nothing: the same trap the incursion board's controls already pay for. Measured at 26px
   before this. The moveable layers are deliberately NOT included: they are
   pointer-events: none (the stack handles the pointer) and exist as buttons only so the
   artwork is keyboard reachable, so forcing a 44px box would distort the render for a
   target nobody taps. */
/* Checkbox rows inside the v2 workbench. Scoped to .dr2-panel rather than to
   `.inline-row` itself, which is a generic class used all over the site: this is a
   dressing-room touch fix, not a site-wide restyle. A 13px UA checkbox in a 25px row is
   the smallest target on the page. */
@media (pointer: coarse) {
    .dr2-panel label.inline-row { min-height: 44px; }
    .dr2-panel label.inline-row input[type="checkbox"] { width: 22px; height: 22px; }
}

@media (pointer: coarse) {
    .dr2-stagebar .btn,
    .dr2-tools__menu .btn,
    .dr2-inspector .btn,
    .dr2-tryon .btn,
    .dr2-collection .btn,
    .dr2-hub-head .btn,
    .dr2-empty-filter .btn {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }
}

