/* patchwork.css: Staff gifts and the gift page; Thistle's Patchwork (.pwk-*) and the Design tab (.dsn-*). */
/* ==========================================================================
   Staff gifts (/staff/gifts/) and the player's gift page (/gifts/<id>/)
   ========================================================================== */
.staff-gift-form { display: flex; flex-direction: column; gap: 18px; }
.staff-gift-form__group { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 12px 14px; margin: 0; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.staff-gift-form__group legend { padding: 0 6px; font-weight: 600; color: var(--text-primary); }
.staff-gift-field { display: flex; flex-direction: column; gap: 4px; font-size: 0.82rem; color: var(--text-muted); min-width: 0; }
.staff-gift-field input, .staff-gift-field textarea, .staff-gift-field select { width: 100%; }
.staff-gift-field textarea { resize: vertical; }
.staff-gift-audience { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.staff-gift-audience__option { display: inline-flex; align-items: center; gap: 6px; color: var(--text-primary); }
.staff-gift-currencies { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.staff-gift-item-row { display: grid; grid-template-columns: minmax(0, 1fr) 110px; gap: 12px; align-items: end; }
.staff-gift-preview { min-height: 2.5em; display: flex; flex-direction: column; gap: 6px; }
.staff-gift-preview__errors { margin: 0; padding-left: 26px; }
.staff-gift-preview__count { margin: 0; }

.staff-gift-detail { max-width: 640px; }
.staff-gift-detail__date { color: var(--text-secondary); }
.staff-gift-detail__note { margin: 14px 0; padding: 10px 14px; border-left: 3px solid var(--color-primary); background: var(--bg-surface); border-radius: var(--radius-sm); color: var(--text-primary); }
.staff-gift-detail__contents { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

@media (width < 768px) {
    .staff-gift-item-row { grid-template-columns: minmax(0, 1fr) 90px; }
}

/* ---- Coarse pointer floor: last in the block for the usual cascade reason ---- */
@media (pointer: coarse) {
    .staff-gift-audience__option { min-height: 44px; }
}
/* =========================================================================
   Thistle's Patchwork: Activities hub, commission workbench, cutting mat
   (.pwk-*). One contiguous block, like .ib2-* and .sq2-*: the mat partial is
   shared with the Design tab, so it styles off data-* states the Alpine
   component binds (data-fabric, data-preview, data-edges, data-holding,
   data-placed), never off classes it would have to remove. Fabric is carried
   by a letter and a weave pattern as well as the piece's color, and every
   state also reads in words in the cell's accessible name and the status line.
   Piece colors are the player's cloth and stay literal; the rest are tokens.

   The commission page is one workbench: goals, mat, basket, controls and the
   client pet all on screen at once. .pwk-page is the container its layout
   queries (so a sidebar's width counts), and .pwk-bench is the container the
   mat sizes its cells from.
   ========================================================================= */

/* ---- Thistle's line: a small bubble, not a portrait block ---- */
.pwk-say .persona-surface { display: flex; gap: 10px; align-items: center; }
.pwk-say__portrait {
    flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%; overflow: hidden;
    background: var(--bg-subtle); display: grid; place-items: center;
}
.pwk-say__portrait img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.pwk-say__placeholder { font-size: 1.35rem; line-height: 1; }
.pwk-say__line {
    margin: 0; padding: 6px 12px; border-radius: var(--radius-lg); background: var(--bg-subtle);
    color: var(--text-secondary); font-style: italic; font-size: 0.88rem; line-height: 1.35; max-width: 60ch;
}

/* ---- Hub ---- */
.pwk-hub { container: pwk-hub / inline-size; }
.pwk-hub .pwk-say { margin: 4px 0 6px; }
.pwk-hub__title { font-size: 1rem; margin: 20px 0 8px; }
.pwk-daily { margin: 0 0 12px; color: var(--text-secondary); font-size: 0.92rem; max-width: 78ch; }
.pwk-daily--capped { color: var(--text-primary); }

.pwk-board { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.pwk-card__link {
    display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 14px; align-items: start; height: 100%; padding: 14px;
    border: 1px solid var(--border-color); border-radius: var(--radius-lg); background: var(--bg-surface);
    color: var(--text-primary); text-decoration: none;
}
.pwk-card__link:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }
@media (hover: hover) {
    .pwk-card__link:hover { border-color: var(--color-primary); }
}
.pwk-card__body { display: flex; flex-direction: column; gap: 4px; min-width: 0; height: 100%; }
.pwk-card__tier { align-self: flex-start; }
.pwk-card[data-tier="medium"] .pwk-card__tier { border-style: dashed; }
.pwk-card[data-tier="hard"] .pwk-card__tier { border-width: 2px; }
.pwk-card__title { font-family: var(--font-heading); font-size: 1.08rem; font-weight: 700; }
.pwk-card__client, .pwk-card__facts, .pwk-card__progress { color: var(--text-secondary); font-size: 0.86rem; }
.pwk-card__progress { color: var(--text-primary); }
.pwk-card__foot { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 10px; margin-top: auto; padding-top: 6px; }
.pwk-card__reward { font-size: 0.9rem; font-weight: 600; }
.pwk-card__action { color: var(--color-primary); font-weight: 700; font-size: 0.9rem; }

/* The job, drawn: the mat's size, its marked zone, its cut-outs, and any cloth already on it. */
.pwk-mini {
    display: grid; grid-template-columns: repeat(var(--pwk-cols), 11px); grid-auto-rows: 11px; gap: 2px;
    padding: 6px; border-radius: var(--radius-md); background: var(--bg-subtle);
}
.pwk-mini__cell { border-radius: 2px; background: var(--bg-surface); border: 1px solid var(--border-subtle); }
.pwk-mini__cell[data-zone="true"] { border-color: var(--color-primary); }
.pwk-mini__cell[data-cutout="true"] { background: transparent; border-style: dashed; border-color: var(--border-color); }
.pwk-mini__cell[data-fabric] { background: var(--pwk-color); border-color: rgba(0, 0, 0, 0.25); }

/* Thistle's patterns: a list on a phone, a track when there's room. */
.pwk-ladder__note { color: var(--text-secondary); font-size: 0.92rem; margin: 0 0 10px; max-width: 78ch; }
.pwk-ladder__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.pwk-ladder__row { display: grid; grid-template-columns: 2.25rem minmax(0, 1fr); gap: 10px; align-items: center; }
.pwk-ladder__count {
    display: grid; place-items: center; width: 2.25rem; height: 2.25rem; border-radius: 50%;
    border: 2px solid var(--border-color); background: var(--bg-surface); font-weight: 700; font-family: var(--font-mono);
}
.pwk-ladder__row[data-reached="true"] .pwk-ladder__count { border-color: var(--color-primary); background: var(--color-primary); color: var(--text-inverse); }
.pwk-ladder__row[data-next="true"] .pwk-ladder__count { border-color: var(--color-primary); border-style: dashed; }
.pwk-ladder__body { display: grid; gap: 1px; min-width: 0; }
.pwk-ladder__families { font-weight: 600; font-size: 0.92rem; }
.pwk-ladder__state { font-size: 0.82rem; color: var(--text-secondary); }
.pwk-ladder__row[data-reached="true"] .pwk-ladder__state { color: var(--color-success-text); }
.pwk-ladder__row[data-next="true"] .pwk-ladder__state { color: var(--text-primary); font-weight: 600; }
@container pwk-hub (width >= 640px) {
    .pwk-ladder__list { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0; position: relative; }
    .pwk-ladder__list::before {
        content: ""; position: absolute; top: calc(1.125rem - 1px); left: 10%; right: 10%; height: 2px; background: var(--border-color);
    }
    .pwk-ladder__row { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; gap: 6px; padding: 0 6px; position: relative; }
}

/* ---- Commission workbench ---- */
.pwk-page { container: pwk-page / inline-size; }
.pwk-run {
    display: grid; gap: 12px; align-items: start;
    grid-template-columns: minmax(0, 1fr) 96px;
    grid-template-areas: "head head" "say say" "goals pet" "bench bench" "bar bar" "tray tray" "key key";
}
.pwk-run:has(.pwk-preview[data-big="true"]) {
    grid-template-areas: "head head" "say say" "goals goals" "pet pet" "bench bench" "bar bar" "tray tray" "key key";
}
.pwk-run[data-delivered="true"] {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "head" "say" "result" "pet" "bench" "goals" "key";
}
@container pwk-page (width < 360px) {
    .pwk-run:not([data-delivered="true"]) { grid-template-columns: minmax(0, 1fr) 72px; }
}
/* Phone: the client pet sits beside the title and Thistle's line, and the goals take the
   full width as one line each (short name and count; the sentences are in "About this
   job"), so the mat starts about 200px higher on a hard brief. */
@container pwk-page (width < 680px) {
    .pwk-run:not([data-delivered="true"]):not(:has(.pwk-preview[data-big="true"])) {
        grid-template-areas: "head pet" "say pet" "goals goals" "bench bench" "bar bar" "tray tray" "key key";
    }
    .pwk-run:not([data-delivered="true"]) .pwk-goal__full { display: none; }
    .pwk-run:not([data-delivered="true"]) .pwk-goal__short { display: inline; }
    .pwk-run:not([data-delivered="true"]) .pwk-about__goals { display: block; }
    .pwk-run:not([data-delivered="true"]) .pwk-goals { gap: 6px; }
    .pwk-run:not([data-delivered="true"]) .pwk-goal__meter { height: 4px; }
    .pwk-run:not([data-delivered="true"]) .pwk-goalbar { padding: 8px 10px; }
    /* The title shares its row with the pet, so the back link is just its arrow (its
       accessible name stays "Back to the board") and the title steps down a size. */
    .pwk-run:not([data-delivered="true"]) .pwk-head { gap: 8px; }
    .pwk-run:not([data-delivered="true"]) .pwk-head__back { min-width: 44px; justify-content: center; padding: 0 10px; }
    .pwk-run:not([data-delivered="true"]) .pwk-head__back-word { display: none; }
    .pwk-run:not([data-delivered="true"]) .pwk-head__title { font-size: 1.1rem; }
    .pwk-run:not([data-delivered="true"]) .pwk-head__meta { font-size: 0.8rem; }
}
.pwk-run .pwk-editor { display: contents; }
.pwk-head { grid-area: head; }
.pwk-say { grid-area: say; }
.pwk-result { grid-area: result; }
.pwk-goalbar { grid-area: goals; }
.pwk-preview { grid-area: pet; }
.pwk-run .pwk-bench { grid-area: bench; }
.pwk-run .pwk-tray { grid-area: tray; }
.pwk-run .pwk-bar { grid-area: bar; }
.pwk-run .pwk-key { grid-area: key; }
.pwk-run noscript { grid-column: 1 / -1; }

@container pwk-page (width >= 680px) {
    .pwk-run, .pwk-run:has(.pwk-preview[data-big="true"]) {
        gap: 14px 18px;
        grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
        grid-template-areas: "head say" "bench goals" "bench pet" "bar pet" "tray pet" "key key";
    }
    .pwk-run[data-delivered="true"] {
        grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
        grid-template-areas: "head say" "result result" "bench pet" "bench goals" "key key";
    }
    .pwk-say { align-self: center; }
}
@container pwk-page (width >= 1040px) {
    .pwk-run, .pwk-run:has(.pwk-preview[data-big="true"]) {
        grid-template-columns: minmax(190px, 0.8fr) minmax(0, 1.6fr) minmax(250px, 1fr);
        grid-template-areas: "head head say" "tray bench goals" "tray bench pet" "tray bar pet" "key key key";
    }
    .pwk-run[data-delivered="true"] {
        grid-template-columns: minmax(250px, 1fr) minmax(0, 1.6fr) minmax(250px, 1fr);
        grid-template-areas: "head head say" "result bench pet" "result bench goals" "key key key";
    }
}

/* Title row */
.pwk-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.pwk-head__back {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 0 12px;
    border: 1px solid var(--border-color); border-radius: var(--radius-pill); color: var(--text-primary);
    text-decoration: none; font-weight: 600; font-size: 0.9rem;
}
.pwk-head__back:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }
@media (hover: hover) {
    .pwk-head__back:hover { border-color: var(--color-primary); }
}
.pwk-head__titles { min-width: 0; }
.pwk-head__title { margin: 0; font-family: var(--font-heading); font-size: 1.3rem; line-height: 1.2; }
.pwk-head__meta { margin: 2px 0 0; color: var(--text-secondary); font-size: 0.86rem; }

/* Goals */
.pwk-goalbar {
    min-width: 0; padding: 10px 12px; border: 1px solid var(--border-color); border-radius: var(--radius-lg); background: var(--bg-surface);
}
.pwk-goals { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.pwk-goal { display: grid; grid-template-columns: 1.1rem minmax(0, 1fr) auto; gap: 2px 6px; align-items: baseline; }
.pwk-goal__mark { font-weight: 700; color: var(--text-muted); }
.pwk-goal[data-met="true"] .pwk-goal__mark { color: var(--color-success-text); }
.pwk-goal__label { font-size: 0.85rem; font-weight: 600; line-height: 1.3; }
.pwk-goal__count { font: 700 0.8rem/1.3 var(--font-mono); color: var(--text-secondary); white-space: nowrap; }
.pwk-goal[data-met="true"] .pwk-goal__count { color: var(--color-success-text); }
.pwk-goal__meter { grid-column: 2 / -1; height: 6px; border-radius: 3px; background: var(--bg-subtle); overflow: hidden; }
.pwk-goal__fill { display: block; height: 100%; max-width: 100%; border-radius: inherit; background: var(--color-primary); }
.pwk-goal[data-met="true"] .pwk-goal__fill { background: var(--color-success); }
.pwk-goal__meter { position: relative; }
.pwk-goal__band { position: absolute; top: 0; bottom: 0; right: 0; background: var(--border-color); opacity: 0.6; }
.pwk-goal__fill { position: relative; }
.pwk-goal[data-over="true"] .pwk-goal__mark,
.pwk-goal[data-over="true"] .pwk-goal__count { color: var(--color-warning-ink); }
.pwk-goal[data-over="true"] .pwk-goal__fill {
    background: repeating-linear-gradient(135deg, var(--color-warning) 0 4px, transparent 4px 8px), var(--color-warning-bg);
}
.pwk-goal__short, .pwk-about__goals { display: none; }
.pwk-about { margin-top: 8px; font-size: 0.85rem; color: var(--text-secondary); }
.pwk-touch { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--border-color); }
.pwk-touch__title { margin: 0; display: flex; gap: 8px; align-items: baseline; }
.pwk-touch__optional { font-size: 0.75rem; color: var(--text-muted); }
.pwk-touch__goal { margin: 4px 0 0; display: grid; grid-template-columns: 1.1rem minmax(0, 1fr) auto; gap: 2px 6px; align-items: baseline; }
.pwk-touch__label { font-size: 0.85rem; font-weight: 600; line-height: 1.3; }
.pwk-touch__state { font: 700 0.8rem/1.3 var(--font-mono); color: var(--text-secondary); white-space: nowrap; }
.pwk-touch[data-met="true"] .pwk-touch__state, .pwk-touch[data-met="true"] .pwk-goal__mark { color: var(--color-success-text); }
.pwk-touch__note { margin: 4px 0 0; font-size: 0.78rem; color: var(--text-secondary); }
.pwk-helpers { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; }
.pwk-helpers form { margin: 0; max-width: none; }
.pwk-helpers__note { margin: 0; flex-basis: 100%; font-size: 0.78rem; color: var(--text-secondary); }
.pwk-ladder__kind { font-weight: 400; color: var(--text-secondary); }
.pwk-about__goals { margin: 6px 0 0; padding-left: 1.2rem; }
.pwk-about summary { cursor: pointer; color: var(--text-primary); font-weight: 600; text-align: start; }
.pwk-about p { margin: 6px 0 0; max-width: 70ch; }

/* The client pet. Small beside the goals on a phone (Bigger opens it out); full size
   wherever there's a column for it. */
.pwk-preview { position: relative; min-width: 0; display: grid; gap: 6px; justify-items: center; align-content: start; }
.pwk-preview__title { margin: 0; font-size: 0.95rem; justify-self: start; }
.pwk-preview__stage {
    position: relative; width: 100%; max-width: 320px; aspect-ratio: 1; border-radius: var(--radius-md);
    background: var(--bg-subtle); overflow: hidden;
}
.pwk-preview__layer, .pwk-preview__pet { position: absolute; inset: 0; width: 100%; height: 100%; }
.pwk-preview__pet { object-fit: contain; z-index: 2; }
.pwk-preview__layer:first-child { z-index: 1; }
.pwk-preview__layer:last-child { z-index: 3; }
.pwk-preview__stage[data-loading="true"] { opacity: 0.7; }
.pwk-preview__nopet { position: absolute; inset: auto 0 8px; text-align: center; font-size: 0.8rem; color: var(--text-muted); z-index: 2; }
.pwk-preview__caption, .pwk-preview__status { margin: 0; font-size: 0.85rem; color: var(--text-secondary); justify-self: start; }
.pwk-preview__chip { margin-left: 4px; }
.pwk-preview__toggle {
    min-height: 32px; padding: 0 10px; border: 1px solid var(--border-color); border-radius: var(--radius-pill);
    background: var(--bg-surface); color: var(--text-primary); font-size: 0.8rem; font-weight: 600; cursor: pointer;
}
.pwk-preview__toggle:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }
.pwk-run:not([data-delivered="true"]) .pwk-preview:not([data-big="true"]) .pwk-preview__title,
.pwk-run:not([data-delivered="true"]) .pwk-preview:not([data-big="true"]) .pwk-preview__caption {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.pwk-run[data-delivered="true"] .pwk-preview__toggle { display: none; }
@container pwk-page (width >= 680px) {
    .pwk-preview .pwk-preview__title, .pwk-preview .pwk-preview__caption {
        position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal;
    }
    .pwk-preview__toggle { display: none; }
}

/* ---- The mat ---- */
.pwk-editor { display: grid; gap: 12px; grid-template-columns: minmax(0, 1fr); grid-template-areas: "bench" "bar" "tray" "key"; }
.pwk-bench { grid-area: bench; min-width: 0; container: pwk-bench / inline-size; display: grid; justify-items: center; }
.pwk-bar { grid-area: bar; }
.pwk-tray { grid-area: tray; min-width: 0; }
.pwk-key { grid-area: key; }
.pwk-mat {
    --pwk-axis: 1rem;
    --pwk-gap: 3px;
    --pwk-cell: clamp(40px, calc((100cqi - var(--pwk-axis) - var(--pwk-cols) * var(--pwk-gap)) / var(--pwk-cols)), 60px);
    display: grid; gap: var(--pwk-gap);
    grid-template-columns: var(--pwk-axis) repeat(var(--pwk-cols), var(--pwk-cell));
    grid-template-rows: var(--pwk-axis);
    grid-auto-rows: var(--pwk-cell);
    user-select: none; -webkit-user-select: none;
}
@container pwk-bench (width < 300px) {
    .pwk-mat { --pwk-axis: 10px; --pwk-gap: 1px; }
    .pwk-mat__axis { font-size: 0.62rem; }
}
.pwk-mat__axis, .pwk-mat__corner { display: grid; place-items: center; font-size: 0.72rem; color: var(--text-muted); font-family: var(--font-mono); }
.pwk-cell {
    position: relative; padding: 0; margin: 0; min-width: 0; min-height: 0;
    border: 1px solid var(--border-color); border-radius: 4px;
    background-color: var(--bg-subtle); color: #fff; cursor: pointer;
    display: grid; place-items: center; touch-action: manipulation;
}
/* With a piece in hand a finger on the mat drags it rather than scrolling the page. */
.pwk-mat[data-holding="true"] .pwk-cell { touch-action: none; }
.pwk-cell[data-fabric] { background-color: var(--pwk-color); border-color: rgba(0, 0, 0, 0.18); }
.pwk-cell[data-fabric="warm"], .pwk-swatch[data-fabric="warm"], .pwk-piece[data-fabric="warm"] .pwk-piece__cell {
    background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.16) 0 3px, transparent 3px 8px);
}
.pwk-cell[data-fabric="durable"], .pwk-swatch[data-fabric="durable"], .pwk-piece[data-fabric="durable"] .pwk-piece__cell {
    background-image:
        repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.18) 0 2px, transparent 2px 7px),
        repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.18) 0 2px, transparent 2px 7px);
}
.pwk-cell[data-fabric="water"], .pwk-swatch[data-fabric="water"], .pwk-piece[data-fabric="water"] .pwk-piece__cell {
    background-image: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.2) 0 2px, transparent 2px 7px);
}
.pwk-cell[data-edges~="t"] { border-top: 2px solid rgba(0, 0, 0, 0.6); }
.pwk-cell[data-edges~="r"] { border-right: 2px solid rgba(0, 0, 0, 0.6); }
.pwk-cell[data-edges~="b"] { border-bottom: 2px solid rgba(0, 0, 0, 0.6); }
.pwk-cell[data-edges~="l"] { border-left: 2px solid rgba(0, 0, 0, 0.6); }
.pwk-cell__letter { position: relative; z-index: 2; }
.pwk-cell__letter:not(:empty) {
    min-width: 1.4em; padding: 0 3px; border-radius: 4px; font: 700 0.78rem/1.4 var(--font-mono);
    background: rgba(0, 0, 0, 0.6); color: #fff;
}
.pwk-cell--zone { outline: 2px dashed var(--color-primary); outline-offset: -6px; }
.pwk-cell--cutout {
    cursor: not-allowed; border-style: dashed;
    background-image: repeating-linear-gradient(-45deg, var(--border-color) 0 2px, transparent 2px 7px);
}
/* The piece in hand: drawn in its own cloth, raised, with a green edge when it fits and a
   red hatch over every square it can't have. The status line says the same in words. */
.pwk-cell[data-preview] { z-index: 1; }
.pwk-cell[data-preview="fit"] { box-shadow: inset 0 0 0 3px var(--color-success), 0 3px 8px rgba(0, 0, 0, 0.35); }
.pwk-cell[data-preview="clash"] { box-shadow: inset 0 0 0 3px var(--color-error); }
.pwk-cell[data-preview="clash"]::before {
    content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: 1;
    background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--color-error) 55%, transparent) 0 3px, transparent 3px 7px);
}
.pwk-cell:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 1px; z-index: 3; }
/* Where patchworkMat.revealGhost scrolls a cell to: clear of the sticky header, and of the
   tab bar on a phone. The Design tab adds its pinned stage (.dsn-* block). */
.pwk-cell { scroll-margin-top: calc(var(--header-height) + 12px); }
@media (width < 768px) {
    .pwk-cell { scroll-margin-bottom: calc(var(--tabbar-height) + 12px); }
}
.pwk-cell[aria-disabled="true"] { cursor: default; }

/* ---- Basket tray: a strip that scrolls sideways on a phone, a grid with room ---- */
.pwk-tray__title { margin: 0 0 6px; font-size: 0.82rem; font-weight: 700; color: var(--text-secondary); letter-spacing: 0.02em; }
.pwk-basket {
    --pwk-mini: 10px;
    list-style: none; margin: 0; padding: 2px 2px 6px; display: flex; gap: 8px;
    overflow-x: auto; scroll-snap-type: x proximity; overscroll-behavior-x: contain;
}
.pwk-basket > li { flex: 0 0 auto; scroll-snap-align: start; }
.pwk-piece {
    width: 96px; height: 100%; min-height: 88px; display: grid; justify-items: center; align-content: start; gap: 3px;
    padding: 7px 5px; text-align: center; line-height: 1.15;
    border: 1px solid var(--border-color); border-radius: var(--radius-md); background: var(--bg-surface); color: var(--text-primary); cursor: pointer;
}
.pwk-piece:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }
.pwk-piece[aria-pressed="true"] { border-color: var(--color-primary); box-shadow: inset 0 0 0 2px var(--color-primary); background: var(--bg-hover); }
.pwk-piece[data-placed="true"]:not([aria-pressed="true"]) { opacity: 0.6; }
.pwk-piece__shape { display: grid; gap: 1px; min-height: 30px; align-content: center; justify-content: center; }
.pwk-piece__cell { width: var(--pwk-mini); height: var(--pwk-mini); background-color: var(--pwk-color); border-radius: 1px; }
.pwk-piece__name { font-weight: 700; font-size: 0.78rem; }
.pwk-piece__meta { font-size: 0.72rem; color: var(--text-secondary); }
.pwk-piece__letter { font-family: var(--font-mono); font-weight: 700; }
.pwk-piece__placed { font-size: 0.72rem; color: var(--color-success-text); font-weight: 600; }
@container pwk-page (width >= 680px) {
    .pwk-run .pwk-basket { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); overflow: visible; }
    .pwk-run .pwk-piece { width: 100%; }
}

/* ---- Action bar: right under the mat, the same size whatever it says, so nothing
   jumps after a move. Mat, bar and basket sit together and fit one phone screen, so
   the bar needs no pinning. ---- */
.pwk-bar {
    min-width: 0; display: grid; gap: 6px; padding: 8px 10px; container: pwk-bar / inline-size;
    border: 1px solid var(--border-color); border-radius: var(--radius-lg); background: var(--bg-elevated);
}
.pwk-bar__status {
    margin: 0; min-height: 2.5em; font-size: 0.85rem; line-height: 1.25; color: var(--text-secondary);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
@container pwk-bar (width < 400px) {
    .pwk-bar__long { display: none; }
}
.pwk-bar__status[data-tone="ok"] { color: var(--color-success-text); }
.pwk-bar__status[data-tone="warn"] { color: var(--color-warning-text); }
.pwk-bar__status[data-tone="error"] { color: var(--color-error-text); }
.pwk-bar__status[data-tone="warn"], .pwk-bar__status[data-tone="error"] { display: block; -webkit-line-clamp: unset; overflow: visible; }
.pwk-bar__buttons { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pwk-bar__spacer { flex: 1 1 0; }
.pwk-tool {
    display: grid; justify-items: center; align-content: center; gap: 1px; min-width: 48px; min-height: 48px; padding: 4px 6px;
    border: 1px solid var(--border-color); border-radius: var(--radius-md); background: var(--bg-surface); color: var(--text-primary);
    font-size: 0.72rem; font-weight: 600; cursor: pointer;
}
.pwk-tool__icon { font-size: 1.1rem; line-height: 1; }
.pwk-tool:disabled { opacity: 0.45; cursor: not-allowed; }
.pwk-tool:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }
@media (hover: hover) {
    .pwk-tool:not(:disabled):hover { border-color: var(--color-primary); }
    .pwk-piece:hover { border-color: var(--color-primary); }
}
.pwk-bar__primary { min-height: 48px; padding: 0 18px; }
.pwk-deliver { margin: 0; }
/* A disabled primary button kept its teal at 60% opacity and still read as ready to press. */
.pwk-bar .btn-primary:disabled {
    background: var(--bg-subtle); color: var(--text-muted); border-color: var(--border-color); box-shadow: none; opacity: 1;
}

/* ---- Key and controls ---- */
.pwk-key { font-size: 0.86rem; color: var(--text-secondary); }
.pwk-key summary { cursor: pointer; display: inline-flex; align-items: center; justify-content: flex-start; min-height: 32px; color: var(--text-primary); font-weight: 600; }
.pwk-legend { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 14px; }
.pwk-legend li { display: inline-flex; align-items: center; gap: 6px; }
.pwk-swatch {
    display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 4px;
    background-color: #6e5c48; color: #fff; font: 700 0.7rem/1 var(--font-mono); border: 1px solid rgba(0, 0, 0, 0.3);
}
.pwk-swatch--zone { background: var(--bg-subtle); outline: 2px dashed var(--color-primary); outline-offset: -5px; }
.pwk-swatch--cutout { background: var(--bg-subtle); color: var(--text-primary); border-style: dashed; }
.pwk-help { margin: 8px 0 0; max-width: 70ch; }
.pwk-nojs { display: grid; gap: 12px; margin-top: 12px; }
.pwk-nojs__form { display: flex; flex-wrap: wrap; gap: 8px; align-items: end; }

/* ---- Delivered ---- */
.pwk-result { margin: 0; }
.pwk-result__pay { font-size: 1.05rem; }
.pwk-result__unlock { padding: 8px 10px; border-left: 3px solid var(--color-primary); background: var(--bg-subtle); border-radius: var(--radius-sm); }
.pwk-result__next { color: var(--text-secondary); }
.pwk-result h2:focus { outline: 3px solid var(--color-primary); outline-offset: 2px; }
.pwk-save { margin-top: 14px; }
.pwk-save__title { font-size: 1rem; margin: 18px 0 10px; }
.pwk-save__form { display: flex; flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: end; }
.pwk-save__label { display: grid; gap: 4px; }
.pwk-save__note { margin: 8px 0 0; font-size: 0.85rem; color: var(--text-muted); max-width: 70ch; }
.pwk-save__done { color: var(--color-success-text); font-weight: 600; }

/* ---- Coarse pointer floor: last in the block for the usual cascade reason ---- */
@media (pointer: coarse) {
    .pwk-mat { --pwk-cell: clamp(44px, calc((100cqi - var(--pwk-axis) - var(--pwk-cols) * var(--pwk-gap)) / var(--pwk-cols)), 60px); }
    .pwk-head__back, .pwk-preview__toggle, .pwk-key summary, .pwk-about summary { min-height: 44px; }
    .pwk-about summary { display: flex; align-items: center; justify-content: flex-start; }
    .pwk-tool, .pwk-bar__primary, .pwk-save__form .btn, .pwk-save__form select { min-height: 48px; }
}

/* =========================================================================
   Patchwork Design tab (.dsn-*): the Dressing Room's saved designs, the
   free-design editor (which reuses the .pwk-* cutting mat), making, and the
   stage preview. One contiguous block, like .pwk-* and .dr2-*. Every colour
   is a token except the player's own cloth, which rides --dsn-c / --dsn-a /
   --dsn-b and stays literal. Status is a glyph plus a word, never colour
   alone. The shared editor stacks here (mat, controls, piece style, pieces),
   and its mat sizes from its own .pwk-bench container.
   ========================================================================= */
.dsn { display: grid; gap: 16px; container-type: inline-size; }
.dsn-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 12px; }
.dsn-title { margin: 0; }
.dsn-title:focus { outline: 3px solid var(--color-primary); outline-offset: 2px; border-radius: var(--radius-sm); }
.dsn-head__facts { display: flex; flex-wrap: wrap; gap: 4px 12px; margin: 0; font-size: 0.88rem; color: var(--text-secondary); }
.dsn-section { display: grid; gap: 10px; min-width: 0; }
.dsn-section__title { margin: 0; font-size: 1rem; }
.dsn-note { margin: 0; font-size: 0.88rem; color: var(--text-secondary); max-width: 70ch; }

.dsn-paywith { margin: 0; padding: 0; border: 0; min-width: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.dsn-paywith legend { padding: 0; margin-bottom: 6px; font-weight: 600; font-size: 0.9rem; }
.dsn-paywith__option {
    display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 6px 12px;
    border: 1px solid var(--border-color); border-radius: var(--radius-pill); background: var(--bg-subtle); cursor: pointer;
}
.dsn-paywith__option:has(input:checked) { border-color: var(--color-primary); box-shadow: inset 0 0 0 1px var(--color-primary); }
.dsn-paywith__option:focus-within { outline: 2px solid var(--color-primary); outline-offset: 2px; }

.dsn-designs, .dsn-orders, .dsn-families { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.dsn-design {
    display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 12px; padding: 10px;
    border: 1px solid var(--border-color); border-radius: var(--radius-lg); background: var(--bg-surface);
}
.dsn-design.is-highlighted { border-color: var(--color-primary); box-shadow: inset 0 0 0 1px var(--color-primary); }
.dsn-design:focus, .dsn-order:focus { outline: 3px solid var(--color-primary); outline-offset: 2px; }
.dsn-design__body { display: grid; gap: 6px; min-width: 0; }
.dsn-design__name { margin: 0; font-weight: 700; }
.dsn-design__meta, .dsn-make__note { margin: 0; font-size: 0.85rem; color: var(--text-secondary); }
.dsn-design__actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.dsn-inline-form { display: inline-flex; margin: 0; }
.dsn-danger { color: var(--color-error-text); }

/* A saved design's swatch: the board itself, 36 cells, backing hatched. No image is
   stored for a design, so this is drawn from its spec on the server. */
.dsn-thumb { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1px; width: 64px; height: 64px; padding: 2px; border-radius: var(--radius-sm); background: var(--border-subtle); }
.dsn-thumb__cell { background-color: var(--dsn-c); border-radius: 1px; }
.dsn-thumb__cell.is-backing { background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.22) 0 1px, transparent 1px 4px); }
.dsn-swatch--dye { display: block; width: 64px; height: 64px; border-radius: 50%; border: 1px solid var(--border-color); background: linear-gradient(135deg, var(--dsn-a) 0 68%, var(--dsn-b) 68% 100%); }

.dsn-families { grid-template-columns: repeat(auto-fill, minmax(min(100%, 150px), 1fr)); gap: 8px; }
.dsn-family { display: grid; gap: 6px; align-content: start; padding: 10px; border: 1px solid var(--border-color); border-radius: var(--radius-md); background: var(--bg-surface); }
.dsn-family.is-locked { border-style: dashed; background: transparent; }
.dsn-family__name { margin: 0; font-weight: 700; }
.dsn-family__meta { margin: 0; font-size: 0.82rem; color: var(--text-secondary); }
.dsn-family__actions { display: flex; flex-wrap: wrap; gap: 6px; }

.dsn-order { display: grid; gap: 4px; padding: 10px 12px; border: 1px solid var(--border-color); border-left-width: 4px; border-radius: var(--radius-md); background: var(--bg-surface); }
.dsn-order[data-status="ready"] { border-left-color: var(--color-success); }
.dsn-order[data-status="refunded"], .dsn-order[data-status="failed"] { border-left-color: var(--color-warning); }
.dsn-order[data-status="queued"], .dsn-order[data-status="rendering"] { border-left-style: dashed; border-left-color: var(--color-primary); }
.dsn-order__status { margin: 0; font-weight: 700; }
.dsn-order[data-status="ready"] .dsn-order__status { color: var(--color-success-text); }
.dsn-order[data-status="refunded"] .dsn-order__status { color: var(--color-warning-text); }
.dsn-order__name { margin: 0; }
.dsn-order__detail { margin: 0; font-size: 0.85rem; color: var(--text-secondary); }

/* ---- The editor ---- */
.dsn-editor { display: grid; gap: 14px; min-width: 0; }
.dsn-editor__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; }
/* Back and Save pinned at the top of the tray's own scroll. Not on a phone: there the
   stage and tab strip are already pinned, a third pinned row pushed the mat's action bar
   under the bottom nav, and Save is pinned in the corner preview instead. */
@media (width >= 768px) {
    .dsn-editor__head {
        position: sticky; top: 0; z-index: 1; margin: 0 -12px; padding: 6px 12px;
        background: var(--bg-surface); border-bottom: 1px solid var(--border-subtle);
    }
}
.dsn-editor__family { display: grid; gap: 6px; }
.dsn-field { display: grid; gap: 4px; font-size: 0.9rem; font-weight: 600; }
.dsn-field select { max-width: 100%; }
.dsn-mapping-fold summary { min-height: 40px; display: flex; align-items: center; font-size: 0.9rem; font-weight: 600; cursor: pointer; }
.dsn-mapping-fold .dsn-mapping { margin-top: 4px; }
.dsn-mapping { padding: 8px 10px; border-left: 3px solid var(--border-color); background: var(--bg-subtle); border-radius: var(--radius-sm); }
.dsn-preview-bar { display: grid; gap: 6px; }
.dsn-toggle { display: inline-flex; flex-direction: row; align-items: center; justify-content: flex-start; gap: 8px; min-height: 40px; font-size: 0.9rem; font-weight: 400; cursor: pointer; }
.dsn-toggle input { width: auto; margin: 0; flex: 0 0 auto; }
/* The mat sizes its cells from .pwk-bench, so the tray's own width (as narrow as 354px
   on the Classic desk) sets them here too. The action bar stays in flow under the mat:
   the Dressing Room already pins the stage on a phone, and a pinned bar would cover the
   mat rows being picked. The palette comes straight after the bar, as the commission's
   basket does: with Color and cloth between them, the mat and the palette never fit on
   one screen. */
.dsn-editor .pwk-editor { grid-template-areas: "bench" "bar" "tray" "style" "key"; }
.dsn-piece-style { grid-area: style; min-width: 0; border: 1px solid var(--border-subtle); border-radius: var(--radius-md); }
.dsn-piece-style__summary { display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 4px 10px; cursor: pointer; }
.dsn-piece-style__words { display: grid; min-width: 0; line-height: 1.25; }
.dsn-piece-style__title { font-size: 0.9rem; font-weight: 600; }
.dsn-piece-style__now { font-size: 0.82rem; color: var(--text-secondary); overflow-wrap: anywhere; }
.dsn-piece-style__body { display: grid; gap: 10px; padding: 4px 10px 10px; }
.dsn-piece-style__summary .dsn-colors__chip { width: 22px; height: 22px; flex: none; }
.dsn-recolor, .dsn-finish { display: grid; gap: 12px; }
.dsn-finish .dsn-section__title { margin-top: 4px; }
.dsn-save { display: inline-flex; margin: 0; }
.dsn-back[aria-describedby] { color: var(--color-warning-text); }
/* The palette wraps where there's room; on a phone it's one row that scrolls sideways,
   like the commission basket, so picking a shape never scrolls the mat away. */
.dsn-editor .pwk-basket { flex-wrap: wrap; overflow: visible; }
@media (width < 768px) {
    .dsn-editor .pwk-basket { flex-wrap: nowrap; overflow-x: auto; }
    /* The pinned stage's height (published as --dr2-stage-h, so it follows the small and
       big design preview), the tab strip pinned under it (57px) and the mat's A to F
       letters (about 24px), which the mapping notes point at. */
    .dsn-editor .pwk-cell { scroll-margin-top: calc(var(--header-height) + var(--dr2-stage-h, 0px) + 88px); }
}

/* Designing on a phone: the pinned stage shrinks to a corner preview (data-design,
   bound to the designPreview store) and the editor gets the screen. "Bigger preview"
   puts the whole stage back. Never from 768px, where stage and tray sit side by side. */
.dr2-stage__design { display: none; }
/* While a design is open the stage is only a preview: its Undo, Redo and Tools act on worn
   layers, and an apparel Undo beside the mat's own Undo read as the same button. */
.dr2-stage[data-design] .dr2-stagebar { display: none; }
@media (width < 768px) {
    .dr2-stage[data-design] .dr2-stage__design { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; }
    .dr2-stage__design-note { margin: 0; font-size: 0.82rem; color: var(--text-secondary); }
    .dr2-stage[data-design="big"] .dr2-stage__design { margin-top: 4px; }
    .dr2-stage[data-design="small"] { display: flex; align-items: center; gap: 10px; }
    .dr2-stage[data-design="small"] .dr-canvas-frame { flex: none; width: 120px; max-width: 120px; margin: 0; }
    .dr2-stage[data-design="small"] .dr2-stage__design { flex: 1 1 0; min-width: 0; flex-direction: column; align-items: flex-start; }
    .dr2-stage[data-design="small"] > :not(.dr-canvas-frame, .dr2-stage__design) { display: none; }
    /* The big preview stops pinning: pinned, 433px of stage plus the tab strip covered the
       whole mat. It scrolls away with the page, and nothing pins under it any more (the
       !important outranks the measured height dressing-room.js sets inline). */
    .dr2-stage[data-design="big"] { position: relative; scroll-margin-top: var(--header-height); }
    .dr2-layout:has(.dr2-stage[data-design="big"]) { --dr2-stage-h: 0px !important; }
}

.dsn-colors { margin: 0; padding: 0; border: 0; min-width: 0; display: grid; gap: 6px; }
.dsn-colors legend { padding: 0; margin-bottom: 4px; font-size: 0.9rem; font-weight: 600; }
.dsn-colors__swatches { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.dsn-colors__swatch {
    width: 32px; height: 32px; padding: 0; border-radius: 50%; cursor: pointer;
    border: 2px solid var(--bg-surface); box-shadow: 0 0 0 1px var(--border-color); background: var(--dsn-c);
}
.dsn-colors__swatch[aria-pressed="true"] { box-shadow: 0 0 0 3px var(--color-primary); }
.dsn-colors__swatch:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 3px; }
.dsn-colors__custom {
    display: inline-flex; align-items: center; gap: 4px; min-height: 32px; padding: 0 8px 0 2px;
    border: 1px solid var(--border-color); border-radius: var(--radius-pill); font-size: 0.82rem; cursor: pointer;
}
.dsn-colors__custom input[type="color"] { width: 28px; height: 28px; padding: 0; border: 0; background: none; cursor: pointer; }
.dsn-colors__custom:focus-within { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.dsn-colors__now { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 0.85rem; color: var(--text-secondary); }
.dsn-colors__chip { width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--border-color); background: var(--dsn-c); }

/* The wardrobe region is a focus fallback (tabindex="-1") after a scrap removes the last
   copy; programmatic focus is not reliably :focus-visible, so give it a ring outright. */
#wardrobe-content:focus { outline: 2px solid var(--color-primary); outline-offset: 4px; border-radius: var(--radius-md); }

/* ---- The preview on the stage ---- */
/* Two canvases inside the live canvas stack: behind shares the body's z-index (and
   comes first in the document), front sits over every layer. Inert to the pointer, so
   the stack's own hit-testing still reaches the real layers. */
.dsn-stage-layer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.dsn-stage-layer--front { z-index: 900; }
.dsn-stage-layer[hidden] { display: none; }
/* "Hide what <pet> is wearing": everything but the body and the preview steps aside,
   markers included, so the design is judged on the companion alone. */
.dr2-canvas-stack.is-design-solo > .dr2-layer:not(.dr2-layer--body) { visibility: hidden; }
.dr-canvas:has(.dr2-canvas-stack.is-design-solo) .dr-canvas-overlay { visibility: hidden; }
/* Close-up on a moveable prop: the body and every worn layer step aside, so the prop is the
   only thing on the stage. */
.dr2-canvas-stack.is-design-closeup > .dr2-layer { visibility: hidden; }
.dr-canvas:has(.dr2-canvas-stack.is-design-closeup) .dr-canvas-overlay { visibility: hidden; }

/* ---- Coarse pointer floor: last in the block for the usual cascade reason ---- */
@media (pointer: coarse) {
    .dsn-colors__swatch { width: 44px; height: 44px; }
    .dsn-colors__custom, .dsn-paywith__option, .dsn-toggle { min-height: 44px; }
    .dsn-colors__custom input[type="color"] { width: 36px; height: 36px; }
    .dsn-design__actions .btn, .dsn-family__actions .btn, .dsn-order .btn, .dsn-save .btn, .dsn-back, .dsn-field select { min-height: 44px; }
    .dsn-piece-style__summary, .dr2-stage__size, .dr2-stage__save, .dsn-mapping-fold summary { min-height: 44px; }
}


