/* THE DECK SHELL (Steven 2026-11-09, approved). components/_deck_shell.html,
   drawn by base.html in place of the LAYOUT_CARDS header on a page that
   sets deck_shell (the signed-in /home deck). Wiring:
   static/js/shell/deck-shell.js. Tokens only; every rule is scoped to the
   shell (.app-shell--deck-shell, .ds-*), so no other page changes.

   1. the deck fills the screen: no header above it (--hc-top 0), the
      dynamic viewport's height, the safe areas inside each slide, and
      every card swipes the same (EVERY CARD SWIPES THE SAME);
   2. the type icon, top left of each card, and its number;
   3. the two floating buttons, My agent bottom left (Steven 2026-11-10:
      Agent and Market swap places; Market is a disc in each card's right
      column, static/cards/card-col.css) and + bottom right (the red
      thumbs-down's corner), still while the cards pass under them;
   4. the + menu, its rows over the card;
   5. the tray, from the left over the card. */

/* ---- 1. the deck fills the screen ------------------------------------- */
.app-shell--deck-shell {
    --hc-top: 0px;              /* home-cards.css: the deck and the Want Market under the header */
    --tb-card-top: 0px;         /* card.css: a full card's height under the header */
    --ds-glass: color-mix(in srgb, var(--color-dark-900) 62%, transparent);
    /* THE DOCK: one line at the bottom, Market, the card's main button and +,
       one height (Steven 2026-11-09: "align the button on the bottom with
       the plus etc. all that should be the same height"). The card fills
       the slide, so its edges are known: the discs and the card's button
       (static/cards/card-col.css) are placed from these tokens alone,
       nothing measured, nothing to drift. */
    --ds-slide-pad: var(--space-1);                    /* the slide's inset around the card */
    --ds-card-w: calc(100vw - 2 * var(--ds-slide-pad));
    --ds-dock-h: 48px;                                 /* the line's height: the pill's, the discs' */
    --ds-dock-in: var(--space-5);                      /* the card's side edge to a disc: its panel's inset */
    --ds-dock-in-b: var(--space-4);                    /* the card's bottom edge to the line */
    --ds-dock-gap: var(--space-2);                     /* a disc to the pill */
    --ds-dock-side: calc((100vw - var(--ds-card-w)) / 2 + var(--ds-dock-in));
    --ds-dock-bottom: calc(max(var(--ds-slide-pad), env(safe-area-inset-bottom, 0px)) + var(--ds-dock-in-b));
    /* the shell's own names for the same */
    --ds-fab: var(--ds-dock-h);
    --ds-fab-gap: var(--ds-dock-gap);
    --ds-fab-bottom: var(--ds-dock-bottom);
    --ds-row-left: var(--ds-dock-side);
    --ds-row-right: var(--ds-dock-side);
}
@media (min-width: 900px) {
    .app-shell--deck-shell { --ds-slide-pad: var(--space-3); }
}
/* THE CARD'S SHAPE, one rule (Steven 2026-11-09 21:50 and 21:55: "this
   card is not right. it's too short", "I want these cards skinnier so they
   look right"): from 600px wide every card on the deck is a tall playing
   card, 9 wide to 16 tall at most, as tall as the screen allows and
   centred, never stretched wide. ONE WIDTH FOR EVERY CARD, --ds-card-w: a
   stacked card (an action or heat pack) gives the pack's strip its
   --ds-stack-strip and is 9:16 exactly; a single card is the same width and
   the full height, a little skinnier, so Market and + (placed from
   --ds-card-w) sit on every card's corners and nothing jumps between
   cards. Read by: the cards here, the pack's strip and its layers
   (heat-stacks.css), the entry card and a card still coming (card-below).
   Under 600px (a phone) the card is the screen, 4px in, as before: a
   phone held upright is already about 9:16, and a short Safari window
   keeps the card the screen's full height and width. */
.app-shell--deck-shell {
    --ds-stack-strip: calc(var(--space-2) + 52px);   /* heat-stacks.css THE PACK IS A STACK OF CARDS: the back edge's 8px peek and the strip's 52px */
}
@media (min-width: 600px) {
    .app-shell--deck-shell {
        --ds-card-w: min(100vw - 2 * var(--ds-slide-pad), (100vh - 2 * var(--ds-slide-pad) - var(--ds-stack-strip)) * 9 / 16);
    }
    .app-shell--deck-shell .hc-slide > :is(.tb-card, .hc-entry, .card-below-wait),
    .app-shell--deck-shell .hc-slide.hc-heat-card > .tb-card,
    .app-shell--deck-shell .hc-slide > :is(.hc-heat-nav, .hc-heat-end-controls) {
        width: var(--ds-card-w);
        max-width: 100%;
        aspect-ratio: auto;
    }
}
@supports (height: 100dvh) {
    @media (min-width: 600px) {
        .app-shell--deck-shell { --ds-card-w: min(100vw - 2 * var(--ds-slide-pad), (100dvh - 2 * var(--ds-slide-pad) - var(--ds-stack-strip)) * 9 / 16); }
    }
}
.app-shell--deck-shell .hc-deck:not(.hc-deck--market) {
    top: 0;
    bottom: auto;
    height: 100vh;
    height: 100dvh;
}
.app-shell--deck-shell .hc-market { top: 0; }
.app-shell--deck-shell .hc-slide {
    padding-top: max(var(--ds-slide-pad), env(safe-area-inset-top, 0px));
    padding-bottom: max(var(--ds-slide-pad), env(safe-area-inset-bottom, 0px));
}
/* EVERY CARD SWIPES THE SAME (Steven 2026-11-10, the Agents card: "There's
   something going on with the cards and the way they swipe up. Some of
   them are different: like this one, as soon as you slightly touch it
   going up it slides up, rather than have some give like the card here",
   the View agent card that follows the finger and springs back). A box
   that scrolls inside a card kept its swipes to itself (overscroll-
   behavior-y: contain: the Agents card's black panel, the New workflow
   card and a workflow's back, the Packs card, the pack builder, the recipe
   card, the Settings card, a View agent card's back, a market offer's
   back), so the deck never moved under the finger and jumped a whole card
   once the finger lifted (home-cards.js ONE MORE PULL). One rule for every
   card on the deck and the market, today's and any to come: every box in a
   card hands its ends on to the deck, as a card's front and the plan back
   do (card.css THE BACK'S END GIVES LIKE THE FRONT). A box taller than its
   card scrolls inside, and at its top and bottom the browser carries the
   swipe on to the deck, with the finger, springing back on a short pull
   and landing on the next card on a long one; home-cards.js innerScroller
   and pullScroller leave such a box to the browser, so the deck is never
   moved twice. Work inside a card keeps its own swipes: a dialog on the
   card (the Archives layer) and the Passport's open book, where
   home-cards.js never moves the deck either. !important because the card
   sheets set contain on their own boxes with any weight; this rule is the
   deck's, not theirs. */
.app-shell--deck-shell :is([data-hc-deck], [data-hc-market-deck]) > .hc-slide * { overscroll-behavior-y: auto !important; }
.app-shell--deck-shell :is([data-hc-deck], [data-hc-market-deck]) > .hc-slide :is(dialog, [role="dialog"], [aria-modal="true"], [data-passport-book]),
.app-shell--deck-shell :is([data-hc-deck], [data-hc-market-deck]) > .hc-slide :is(dialog, [role="dialog"], [aria-modal="true"], [data-passport-book]) * { overscroll-behavior-y: contain !important; }

/* ---- 2. the type icon -------------------------------------------------- */
/* TOP RIGHT (Steven 2026-11-09 15:50: "Get the card icon in the top right so
   we are managing space"): the first disc of the card's right-hand column,
   42px discs 10px apart, 12px in from the right, 14px down. On a card it
   rides the card's frame, outside its faces (like the three dots); a sheet
   inside the card (.tb-card__layer) covers it. On a slide with no card (the
   entry card, the door) it sits in the same place on the slide, inside the
   safe area. The card's column (Market, Save, Share path and Flip) stands
   centred on the card's right edge; the three dots sit in the card's top
   right corner (static/cards/card-col.css). */
.app-shell--deck-shell {
    --ds-col: 42px;             /* a disc in the right-hand column */
    --ds-col-gap: 10px;
    --ds-col-top: 14px;
    --ds-col-right: 12px;
}
.ds-type {
    position: absolute;
    z-index: var(--z-dropdown);
    /* THE CORNER, one line. Top left would be
       inset: var(--ds-col-top) auto auto var(--ds-col-right); */
    inset: var(--ds-col-top) var(--ds-col-right) auto auto;
    display: inline-grid;
    place-items: center;
    width: var(--ds-col);
    height: var(--ds-col);
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--radius-full);
    background: var(--ds-glass);
    box-shadow: 0 0 0 1px rgb(255 255 255 / 0.08);
    cursor: pointer;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    -webkit-tap-highlight-color: transparent;
}
.hc-slide > .ds-type {
    --ds-col-top: calc(max(var(--space-1), env(safe-area-inset-top, 0px)) + 14px);
    --ds-col-right: calc(var(--space-1) + 12px);
}
.ds-type:focus-visible { outline: 2px solid var(--interactive-focus-ring, var(--color-yellow-400)); outline-offset: 2px; }
.ds-type__glyph { display: inline-grid; place-items: center; }
.ds-type__glyph[hidden] { display: none; }
.tb-card.is-3d > .ds-type { visibility: hidden; }
/* the column (Market, Save, Share path, Flip) and the three dots at the
   card's top are the card's own: static/cards/card-col.css,
   cards/_card.html _col */
/* the title and subtitle keep the site's type at the top left and clear
   the column on the right */
.tb-card:has(> .ds-type) .tb-card__art > .tb-card__head,
.tb-card:has(> .ds-type) .tb-card__backtitle { padding-right: calc(var(--ds-col) + var(--space-1)); }
.tb-card:has(> .ds-type) .tb-card__face--side .tb-side__head { padding-right: calc(var(--space-5) + var(--ds-col) + var(--space-1)); }

/* the number: the purple badge the header's target mark wore */
.ds-badge {
    position: absolute;
    top: calc(-1 * var(--space-1));
    right: calc(-1 * var(--space-1) - 2px);
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    box-sizing: border-box;
    border-radius: var(--radius-full);
    background: var(--color-purple-500);
    box-shadow: 0 0 0 2px var(--color-dark-900);
    color: var(--text-inverse);
    font: 600 12px/20px var(--font-sans);
    text-align: center;
    pointer-events: none;
}

/* ---- 3. the floating buttons ------------------------------------------ */
/* ONE LINE WITH THE CARD'S MAIN BUTTON (Steven 2026-11-09): My agent, then
   the pill filling the middle, then +, the same height, centred on one line:
   the dock's tokens above place both discs, and the card's own pill on the
   same tokens (static/cards/card-col.css). */
.ds-fab {
    position: fixed;
    bottom: var(--ds-fab-bottom);
    z-index: var(--z-overlay);
    display: grid;
    place-items: center;
    width: var(--ds-fab);
    height: var(--ds-fab);
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--radius-full);
    color: var(--text-inverse);
    text-decoration: none;
    cursor: pointer;
    box-shadow: 0 6px 18px rgb(0 0 0 / 0.28);
    -webkit-tap-highlight-color: transparent;
}
.ds-fab:focus-visible { outline: 2px solid var(--color-yellow-400); outline-offset: 2px; }
/* MY AGENT, bottom left (Steven 2026-11-10): the club, the door the card's
   My agent disc had (deck_shell_view().offer_url), on the frosted round
   the card's Save, Share path and Flip wear (static/cards/card-col.css,
   THE FROSTED DISC; Steven 2026-11-10, his reference shot of a pale
   see-through share round: "also the bottom-left corner for the agent to
   also be like this"; then "make the lighter buttons more transparent"):
   white at 55 percent with what is under it blurred through, the club in
   the site's dark ink. NO DROP SHADOW, A GRAY RING (Steven 2026-11-10:
   "I don't think I want this to float. I want it to have a gray line
   around it"): a ring the weight of the card's own line (--cf-hair, the
   border token), drawn inside the round so the disc stays the +'s 48
   across. OVER THE CARD'S COLOUR, INSIDE THE BAND (Steven 2026-11-10, his
   pen sketch: "the left bottom is floating above the color, and the white
   goes all the way around"): no pocket; the card's white band runs on
   unbroken outside the disc and the + (card-frame.css THE BAND GOES ALL
   THE WAY ROUND), and the bottom left corner keeps the circle's curve
   round the disc. */
.ds-fab--agent {
    left: var(--ds-row-left);
    background: color-mix(in srgb, var(--color-white) 55%, transparent);
    box-shadow: inset 0 0 0 var(--cf-hair, var(--tb-hair)) var(--border-strong);
    color: var(--text-primary);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
}
.ds-fab--agent:hover { background: color-mix(in srgb, var(--color-white) 72%, transparent); }
/* the club draws white by its own name (components/_deck_glyphs.html,
   .ds-glyph--agent): on the frosted round it takes the round's dark ink */
.ds-fab--agent > svg { color: inherit; }
.ds-fab--plus { right: var(--ds-row-right); background: var(--color-purple-500); }
.ds-fab--plus:hover { background: color-mix(in srgb, var(--color-purple-500) 85%, var(--color-black, #000)); }
.ds-fab iconify-icon { display: block; width: 26px; height: 26px; font-size: 26px; }
/* out of the way while a sheet or the step's work is over the deck, a
   sheet inside the card is up, or the person is typing: classes deck-shell.js
   keeps on <body> (ds-over, ds-layer, ds-typing), never a body:has(): one
   over [hidden] or :focus made every hidden switch and focus change restyle
   the whole page, and any body:has() made every card put in do it (lane P,
   2026-11-10). */
body.ds-over .ds > .ds-fab,
body.ds-layer .ds > .ds-fab,
body.ds-typing .ds > .ds-fab { display: none; }

/* ---- 4 and 5. the + menu and the tray: modal dialogs over the card ---- */
.ds-menu,
.ds-tray {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    overflow: hidden;
    background: transparent;
    color: var(--text-inverse);
}
.ds-menu:not([open]),
.ds-tray:not([open]) { display: none; }
.ds-menu::backdrop { background: rgb(0 0 0 / 0.35); }
.ds-tray::backdrop { background: rgb(0 0 0 / 0.45); }

/* the + menu: above the +, right aligned; its X where the + is */
.ds-menu__panel {
    position: fixed;
    right: var(--ds-row-right);
    bottom: calc(var(--ds-fab-bottom) + var(--ds-fab) + var(--space-3));
    width: min(300px, calc(100vw - 2 * var(--space-5)));
    box-sizing: border-box;
    padding: var(--space-2);
    border-radius: 22px;
    background: color-mix(in srgb, var(--color-dark-900) 94%, transparent);
    box-shadow: 0 0 0 1px rgb(255 255 255 / 0.08), 0 18px 40px rgb(0 0 0 / 0.45);
    transform-origin: 100% 100%;
    animation: ds-menu-in 0.18s cubic-bezier(.2, .7, .2, 1);
}
@keyframes ds-menu-in { from { opacity: 0; transform: translateY(8px) scale(0.96); } }
.ds-menu__row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    box-sizing: border-box;
    min-height: 60px;
    margin: 0;
    padding: var(--space-2) var(--space-3);
    border: 0;
    border-radius: 16px;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}
.ds-menu__row:hover,
.ds-menu__row:focus-visible { background: rgb(255 255 255 / 0.08); outline: none; }
.ds-menu__row + .ds-menu__row { margin-top: 2px; }
.ds-menu__row[aria-disabled="true"] { opacity: 0.55; cursor: default; }
.ds-menu__ic,
.ds-row__ic {
    flex: none;
    display: inline-grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    background: rgb(255 255 255 / 0.08);
    color: var(--text-inverse);
}
.ds-menu__words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ds-menu__words b { font: 700 16px/1.2 var(--font-heading); }
.ds-menu__words small { color: rgb(255 255 255 / 0.62); font: 400 13px/1.3 var(--font-sans); }
.ds-menu .ds-fab--close { background: var(--color-dark-700); box-shadow: 0 0 0 1px rgb(255 255 255 / 0.12); }

/* the tray */
.ds-tray__panel {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    display: flex;
    flex-direction: column;
    width: min(86vw, 340px);
    box-sizing: border-box;
    padding-top: env(safe-area-inset-top, 0px);
    padding-left: env(safe-area-inset-left, 0px);
    border-radius: 0 var(--radius-hero) var(--radius-hero) 0;
    background: var(--color-dark-900);
    box-shadow: 0 0 0 1px rgb(255 255 255 / 0.06), 18px 0 48px rgb(0 0 0 / 0.5);
    transform: translateX(-100%);
    transition: transform 0.28s cubic-bezier(.2, .7, .2, 1);
}
.ds-tray[open] .ds-tray__panel { transform: none; }
@starting-style { .ds-tray[open] .ds-tray__panel { transform: translateX(-100%); } }
.ds-tray.is-closing .ds-tray__panel { transform: translateX(-100%); transition-duration: 0.2s; transition-timing-function: cubic-bezier(.4, 0, 1, 1); }
.ds-tray__head {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) var(--space-3) var(--space-2) var(--space-5);
}
.ds-tray__brand { font: 800 22px/1 var(--font-heading); letter-spacing: -0.01em; }
.ds-tray__x {
    display: inline-grid;
    place-items: center;
    width: var(--size-10);
    height: var(--size-10);
    padding: 0;
    border: 0;
    border-radius: var(--radius-full);
    background: rgb(255 255 255 / 0.08);
    color: inherit;
    cursor: pointer;
}
.ds-tray__x iconify-icon { width: 22px; height: 22px; font-size: 22px; }
.ds-tray__scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-1) 0 calc(var(--space-6, 24px) + env(safe-area-inset-bottom, 0px));
    -webkit-overflow-scrolling: touch;
}
.ds-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 56px;
    padding: 0 var(--space-5);
    color: inherit;
    font: 700 17px/1.2 var(--font-heading);
    text-decoration: none;
}
.ds-row:hover,
.ds-row:focus-visible,
.ds-link:hover,
.ds-link:focus-visible { background: rgb(255 255 255 / 0.06); outline: none; }
.ds-row__words { flex: 1 1 auto; min-width: 0; }
.ds-row__ic--face { background: none; overflow: hidden; }
.ds-row__ic--face > :is(svg, img) { width: 28px; height: 28px; border-radius: var(--radius-full); }
/* THE PASSPORT ROW (Steven 2026-11-10, his shot of the tray: "this should
   say Name on top like Narefavo. Then below should say your passport. all
   squeezed."): the person's name in the row's own weight, "Your passport"
   under it smaller and muted, the two lines tight, so the row keeps the
   other rows' height; the face stays at the left (_deck_shell.html) */
.ds-row--passport .ds-row__words {
    display: flex;
    flex-direction: column;
    gap: 0;
    line-height: var(--leading-tight);
}
.ds-row__name {
    overflow: hidden;
    color: var(--text-inverse);
    line-height: var(--leading-tight);
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ds-row__sub {
    color: color-mix(in srgb, var(--text-inverse) 62%, transparent);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: var(--font-normal);
    line-height: var(--leading-tight);
}
.ds-row__count,
.ds-link__count {
    flex: none;
    min-width: 22px;
    padding: 0 7px;
    border-radius: var(--radius-full);
    background: var(--color-purple-500);
    color: var(--text-inverse);
    font: 600 12px/22px var(--font-sans);
    text-align: center;
}
.ds-link__count { display: inline-block; margin-left: var(--space-1); line-height: 20px; vertical-align: 1px; }
.ds-tray__label {
    display: block;
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-5) var(--space-1);
    border-top: 1px solid rgb(255 255 255 / 0.08);
    color: var(--color-yellow-400);
    font: 600 11px/1 var(--font-mono);
    letter-spacing: 0.12em;
    text-transform: uppercase;
}
.ds-link {
    display: block;
    padding: 11px var(--space-5);
    color: rgb(255 255 255 / 0.88);
    font: 500 15px/1.3 var(--font-sans);
    text-decoration: none;
}
.ds-tray__house { padding: 0 var(--space-3); }
.ds-tray__house a { color: rgb(255 255 255 / 0.88); }

/* Share path's one quiet line, over the deck above the buttons */
.ds-toast {
    position: fixed;
    left: 50%;
    bottom: calc(var(--ds-fab-bottom) + var(--ds-fab) + var(--space-3));
    z-index: var(--z-overlay);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    max-width: calc(100vw - 2 * var(--space-5));
    box-sizing: border-box;
    padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
    border-radius: var(--radius-full);
    background: var(--color-dark-900);
    box-shadow: 0 0 0 1px rgb(255 255 255 / 0.1), 0 10px 30px rgb(0 0 0 / 0.4);
    color: var(--text-inverse);
    font: 500 14px/1.3 var(--font-sans);
    transform: translateX(-50%);
}
.ds-toast[hidden] { display: none; }
/* no button showing (deck-shell.js keeps ds-toast--act while it shows) */
.ds-toast:not(.ds-toast--act) { padding-right: var(--space-4); }
.ds-toast__act {
    flex: none;
    min-height: 36px;
    padding: 0 var(--space-4);
    border: 0;
    border-radius: var(--radius-full);
    background: var(--color-yellow-400);
    color: var(--color-dark-900);
    font: 700 14px/1 var(--font-heading);
    cursor: pointer;
}
.ds-toast__act[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
    .ds-tray__panel { transition: none; }
    .ds-menu__panel { animation: none; }
}
