/* The animator's phone layout (anim-mobile.html) inside the shell both
   pages share (css/sheet.css): the view toggle in the topbar, the
   status banner, the transport pill, and the three sheets — Puzzle,
   Moves, Explore (the explorer's internals from query.css, neutralized
   where its desktop layout would fight the sheet).  Shared control
   styles come from controls.css, the solve components both shells
   share from solve-common.css, colors from burr-theme.css. */

/* ── Topbar: the 3D / 2D switch beside the title ── */
#topbar-view-toggle { flex: none; }
#topbar-view-toggle .btn { flex: none; min-width: 48px; padding: 0 10px; }
@media (max-width: 359px) {
    #topbar-view-toggle .btn { min-width: 44px; padding: 0 6px; }
}

/* ── Status banner (engine-controlled text/class/display) ── */
#status {
    position: fixed;
    top: calc(var(--topbar-h) + 8px);
    left: calc(12px + env(safe-area-inset-left, 0px));
    right: calc(12px + env(safe-area-inset-right, 0px));
    z-index: 45;
    margin-top: 0;
    box-shadow: var(--shadow-soft);
}

/* The mode toast needs no override: it is absolute inside #stage
   (controls.css .stage-toast), whose bottom already tracks the sheet
   claim. */

/* ── Transport pill ── */
/* Rides the OPEN sheet's real top edge (--sheet-edge, uncapped — the
   stage's own bottom stops at its claim cap, and a tall Moves sheet
   must not end up under the pill), or the tab bar when no sheet is
   open. */
#transport-pill {
    position: fixed;
    /* Centered in the SAFE rectangle: with asymmetric side insets
       (landscape notch) a viewport-centered pill could still reach
       under the housing. */
    left: calc(50% + (env(safe-area-inset-left, 0px)
        - env(safe-area-inset-right, 0px)) / 2);
    transform: translateX(-50%);
    bottom: calc(var(--sheet-edge, var(--tabbar-h)) + 12px);
    z-index: 35;
    max-width: calc(100vw - 16px
        - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px));
    padding: 6px 12px;
    background: var(--panel-strong);
    backdrop-filter: blur(10px);
    border: 1px solid var(--panel-border);
    border-radius: 32px;
    box-shadow: var(--shadow-soft);
}
/* The shell hides the pill while a non-Moves sheet is open; the engine
   hides the inner playback group until a solution loads — an empty pill
   shell must not float around on its own. The shell mirrors the inner
   group's state onto .pill-empty for Safari without :has(). */
body.hide-transport #transport-pill { display: none; }
#transport-pill.pill-empty { display: none; }
#transport-pill:has(> #playback-group.hidden) { display: none; }
#transport-pill .control-group { margin: 0; }
#transport-pill .group-heading { display: none; }  /* no room for a heading */
#transport-pill .playback-row .btn { width: 44px; height: 44px; font-size: 16px; }
#transport-pill .transport { grid-template-columns: repeat(2, 44px); }
/* Damp pill-width jitter as the label counts moves up. */
#transport-pill .move-label { min-width: 9ch; text-align: center; margin-left: 4px; }

/* The pill eases with the sheet it rides (css/sheet.css's snap). */
body.sheet-snapping #transport-pill { transition: bottom 180ms ease-out; }
@media (prefers-reduced-motion: reduce) {
    body.sheet-snapping #transport-pill { transition: none; }
}

/* ── Puzzle sheet: scrolls vertically as one unit ── */
#sheet-puzzle {
    display: block;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* No bottom-inset term: the sheet already sits above the tab bar,
       whose height carries the safe area. */
    padding: 0 calc(16px + env(safe-area-inset-right, 0px)) 16px
             calc(16px + env(safe-area-inset-left, 0px));
    font-size: 13px;    /* desktop-dense 11-12px component text reads
                           too small held at arm's length */
}
/* The loaded puzzle's whole name: the topbar ellipsizes a long one and
   the native select below clips it; this wraps. */
#mobile-puzzle-name {
    margin: 0 0 8px;
    padding: 0 2px 9px;
    border-bottom: 1px solid var(--line-soft);
    color: var(--text);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.3;
}
/* The shared 10-11px hint/info sizes are drawer-scale; bump them to
   the sheet's own scale. */
#sheet-puzzle .hint { font-size: 12px; }
#sheet-puzzle .info { font-size: 13px; }
#view-mode-seg {
    display: grid;      /* 2x2: the long mode labels don't fit one row */
    grid-template-columns: 1fr 1fr;
    gap: 6px;
}
#rotate-cluster {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 6px;
}
#rotate-cluster .btn { padding: 8px 0; }
#rotate-cluster #btn-reset-view { grid-column: 1 / -1; }
/* Six 44px buttons plus gaps outgrow a 320px phone — fold to 3x2. */
@media (max-width: 359px) {
    #rotate-cluster { grid-template-columns: repeat(3, 1fr); }
    /* Six IDs at the input's size need more than the width Solve leaves
       beside it: the button stacks under the input, stretched by the
       grid's single column. */
    #sheet-puzzle .input-row { display: grid; }
}
/* The summary tiles share the width evenly but never squeeze below
   their caption: at 320 wide an even quarter clips "Assemblies". */
#mobile-puzzle-summary {
    display: grid;
    grid-template-columns: repeat(4, minmax(max-content, 1fr));
    gap: 6px;
    margin: 12px 0 2px;
}
#mobile-puzzle-summary .summary-metric {
    padding: 7px 5px;
    border: 1px solid var(--line-soft);
    border-radius: 6px;
    background: var(--field);
    text-align: center;
}
#mobile-puzzle-summary dt {
    color: var(--muted);
    font-size: 9px;
    letter-spacing: .4px;
    text-transform: uppercase;
}
#mobile-puzzle-summary dd {
    margin: 2px 0 0;
    color: var(--text);
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

/* ── Moves sheet: the move list is the scroller ── */
#sheet-moves {
    padding: 0 calc(8px + env(safe-area-inset-right, 0px)) 8px
             calc(8px + env(safe-area-inset-left, 0px));
}
#sheet-moves #move-panel {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
#sheet-moves #move-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 2px 4px 8px;
}
/* Taller rows: each is a tap target.  Full-width rows get away with
   less than 44px; ~38px keeps the list scannable. */
#sheet-moves .move-item { padding: 10px 6px; font-size: 13px; }

/* ── Explore sheet ── */
/* Neutralize query.css's desktop drawer layout: inside the sheet the
   drawer is a plain flex column, the sheet tab replaces its toggle and
   the sheet handle replaces both drag handles, and the results table
   takes whatever height the details rows leave. */
#sheet-explore {
    padding: 0 env(safe-area-inset-right, 0px)
             0 env(safe-area-inset-left, 0px);
}
#sheet-explore #query-drawer {
    position: static;
    box-shadow: none;
    border-top: none;
    background: none;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
#sheet-explore #query-toggle { display: none; }
#sheet-explore #query-facet-handle { display: none; }
#sheet-explore #query-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    height: auto !important;
    border-top: none;
}
.sheet-details { flex: none; border-bottom: 1px solid var(--line-soft); }
.sheet-details summary {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 14px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--muted);
    cursor: pointer;
}
/* display:flex drops the native disclosure marker; the shared rotating
   caret (controls.css .panel-caret) takes its place, matching the
   panel-toggle idiom. */
.sheet-details summary::-webkit-details-marker { display: none; }
.sheet-details[open] summary .panel-caret { transform: rotate(90deg); }
.explore-mode-done {
    display: none;
    margin-left: auto;
    color: var(--accent-text);
    font-weight: 700;
}
.sheet-details[open] .explore-mode-done { display: inline; }
#query-active-filters {
    flex: none;
    display: flex;
    gap: 6px;
    padding: 7px 10px;
    overflow-x: auto;
    scrollbar-width: none;
    border-bottom: 1px solid var(--line-soft);
    overscroll-behavior-x: contain;
}
#query-active-filters::-webkit-scrollbar { display: none; }
.query-filter-chip {
    flex: none;
    padding: 4px 8px;
    border: 1px solid var(--accent);
    border-radius: 999px;
    background: var(--accent-soft);
    color: var(--accent-text);
    font-size: 11px;
    line-height: 16px;
    white-space: nowrap;
}
#sheet-explore #query-facets {
    width: auto;            /* the desktop rail width doesn't apply */
    border-right: none;
    max-height: 40vh;       /* long facet rail scrolls; the table stays */
    max-height: 40dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
}
#sheet-explore .facet-row {
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 8px;
}
#sheet-explore .facet-row > label { flex: 1 1 100%; }
#sheet-explore .facet-row select { min-height: 36px; width: auto; min-width: 72px; }
#sheet-explore .facet-row input[type="number"] { width: 72px; padding: 6px 4px; }
/* The piece-field overlay mirrors the input's font metrics exactly —
   the 16px bump must land on both or the red-ID marks drift. */
#sheet-explore .facet-row input[type="text"] { padding: 6px; line-height: 22px; }
#sheet-explore .piece-wrap { flex: 1; min-width: 160px; }
#sheet-explore .piece-wrap input { width: 100%; box-sizing: border-box; }
#sheet-explore .piece-highlight { padding: 6px; font-size: 16px; line-height: 22px; }
#sheet-explore input.col-toggle { width: 20px; height: 20px; }
/* The 16px desktop toggle slot is too tight a target; widen the whole
   column so the checkboxes stay aligned. A slot carrying a toggle's
   state word or the reset button sizes to those words instead. */
#sheet-explore .facet-slot { width: 28px; }
#sheet-explore .facet-slot:has(.col-toggle-label),
#sheet-explore .facet-slot:has(.col-toggle-reset) { width: auto; }
#sheet-explore .col-toggle-label {
    gap: 6px;
    min-height: 36px;
    padding: 0 6px;
    color: var(--muted);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    white-space: nowrap;
}
#sheet-explore .col-toggle-label:has(.touched) {
    color: var(--accent-text);
    font-weight: 700;
}
#sheet-explore .col-toggle-copy { display: inline; }
/* The reset button says its words: the desktop's 16px square (query.css)
   would keep the box at the 44px minimum and run the text past it. */
#sheet-explore .col-toggle-reset {
    width: auto;
    height: auto;
    min-width: 44px;
    min-height: 36px;
    padding: 0 9px;
    font-size: 10px;
    line-height: 34px;
    white-space: nowrap;
}
#sheet-explore .col-toggle-reset::before { content: none; }
#sheet-explore #query-main { flex: 1; min-height: 0; }
#sheet-explore #query-sql { min-height: 3.5em; }
#sheet-explore #query-statusbar { padding: 4px 10px; }
.query-tap-hint { margin: 0; padding: 0 14px 6px; }
#sheet-explore #query-table-wrap {
    flex: 1;
    min-height: 0;
    overflow: auto;         /* both axes; sticky th works inside */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}
#sheet-explore #query-table td { padding: 8px; }
/* Tap-to-sort headers get finger-sized rows (desktop keeps them slim). */
#sheet-explore #query-table th { padding: 12px 8px; }
/* Hover-title columns (description): titles are unreachable on touch,
   so let the text wrap to a few lines instead of dying in an ellipsis. */
#sheet-explore #query-table td.prose {
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* A disclosure becomes a focused editor while open: native details keep
   the entry/exit affordance, and the editor hides the other row and the
   results, so the two never compete for the sheet's height.  The open
   editor is a flex column down to its content — the facet rail or the
   SQL row — through the details element's own content box
   (::details-content; an engine without it skips that block, and there
   the rail keeps its 40dvh cap and the SQL box its three rows). */
body.explore-filters-open #sheet-explore #query-body > [data-explore-mode="filters"],
body.explore-sql-open #sheet-explore #query-main > [data-explore-mode="sql"] {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
@supports selector(::details-content) {
    body.explore-filters-open #sheet-explore [data-explore-mode="filters"]::details-content,
    body.explore-sql-open #sheet-explore [data-explore-mode="sql"]::details-content {
        flex: 1;
        min-height: 0;
        display: flex;
        flex-direction: column;
    }
    body.explore-filters-open #sheet-explore #query-facets { max-height: none; }
}
/* Filters keeps the status line as its footer, without the pager: the
   facets query as they change, and the count is the one piece of
   feedback the hidden results leave. */
body.explore-filters-open #sheet-explore #query-main { flex: none; }
body.explore-filters-open #sheet-explore #query-main > :not(#query-statusbar),
body.explore-filters-open #sheet-explore #query-statusbar .btn,
body.explore-filters-open #sheet-explore #query-active-filters,
body.explore-sql-open #sheet-explore #query-body > [data-explore-mode="filters"],
body.explore-sql-open #sheet-explore #query-active-filters,
body.explore-sql-open #sheet-explore #query-statusbar,
body.explore-sql-open #sheet-explore .query-tap-hint,
body.explore-sql-open #sheet-explore #query-table-wrap {
    display: none;
}
body.explore-filters-open #sheet-explore #query-facets { flex: 1; }
body.explore-sql-open #sheet-explore #query-sql-row {
    flex: 1;
    min-height: 0;
}
body.explore-sql-open #sheet-explore #query-sql {
    flex: 1;
    resize: none;
}

/* A desktop-width table makes a phone show the least useful fields
   first (hex ID and a clipped name). Below the table's own minimum
   width (query.css) the sheet instead renders the same semantic table
   as cards: the name as title, the pieces, then the other fields in a
   grid, each captioned from its data-label. The header row becomes a
   horizontal strip of sort chips, so converting the rows does not
   remove tap-to-sort. Taller wide screens keep the aligned table;
   short landscape uses cards because its split panel is only half
   the viewport. */
@media (max-width: 759px), (orientation: landscape) and (max-height: 500px) {
    #sheet-explore #query-table-wrap { overflow-x: hidden; }
    #sheet-explore #query-table { display: block; min-width: 0; }
    #sheet-explore #query-table thead,
    #sheet-explore #query-table tbody { display: block; }
    #sheet-explore #query-table thead {
        position: sticky;
        top: 0;
        z-index: 2;
        overflow-x: auto;
        scrollbar-width: none;
        background: var(--bg-accent);
        border-bottom: 1px solid var(--line);
    }
    #sheet-explore #query-table thead::-webkit-scrollbar { display: none; }
    /* Custom SQL makes no header sortable (query-drawer.js), which
       would leave an empty strip; the cards carry the labels anyway.
       Without :has() the empty strip stays, a cosmetic 11px band. */
    #sheet-explore #query-table thead:not(:has(th.sortable)) { display: none; }
    #sheet-explore #query-table thead tr {
        display: flex;
        gap: 6px;
        width: max-content;
        min-width: 100%;
        padding: 5px 10px;
        box-sizing: border-box;
    }
    /* A chip shows the card label from data-label; font-size 0 hides
       the table label text node, so the sort marker (a child span)
       sets its own size back. */
    #sheet-explore #query-table th {
        position: static;
        display: none;
        min-width: 68px;
        min-height: 44px;
        box-sizing: border-box;
        align-items: center;
        padding: 5px 8px;
        border: 1px solid var(--line);
        border-radius: 18px;
        background: var(--field);
        font-size: 0;
    }
    #sheet-explore #query-table th::before {
        content: attr(data-label);
        font-size: 11px;
    }
    #sheet-explore #query-table th.sortable { display: flex; }
    #sheet-explore #query-table th .sort-ind { margin-left: auto; font-size: 11px; }
    /* Sorting by piece list or hex ID is rarely what a thumb is after:
       those two chips go last, behind any extra columns. */
    #sheet-explore #query-table th[data-column="pieces"] { order: 1; }
    #sheet-explore #query-table th[data-column="id"] { order: 2; }
    #sheet-explore #query-table tbody tr {
        display: grid;
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 8px 10px;
        padding: 11px 14px;
        border-bottom: 1px solid var(--line-soft);
    }
    #sheet-explore #query-table tbody tr:active { background: var(--field-strong); }
    #sheet-explore #query-table td {
        display: block;
        min-width: 0;
        padding: 0;
        border: none;
        overflow: hidden;
        font-size: 12px;
        text-align: left;       /* bool cells centre in the table */
        text-overflow: ellipsis;
    }
    #sheet-explore #query-table td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 2px;
        overflow: hidden;       /* "distinct pieces" outgrows a 320px column */
        text-overflow: ellipsis;
        color: var(--muted);
        font-family: var(--font-ui);
        font-size: 9px;
        font-weight: 600;
        line-height: 1;
        letter-spacing: .45px;
        text-transform: uppercase;
    }
    /* The title is the name; an unnamed row shows its hex ID instead
       (the ID of a named row is in the row tooltip, long-press). */
    #sheet-explore #query-table td[data-column="name"] {
        grid-column: 1 / -1;
        font-family: var(--font-ui);
        font-size: 14px;
        font-weight: 600;
    }
    #sheet-explore #query-table td[data-column="name"]::before { display: none; }
    #sheet-explore #query-table td[data-column="id"] { grid-column: 1 / -1; }
    #sheet-explore #query-table tr.named td[data-column="id"],
    #sheet-explore #query-table tr:not(.named) td[data-column="name"] { display: none; }
    #sheet-explore #query-table td[data-column="pieces"] {
        grid-column: 1 / -1;
        color: var(--muted);
        font-size: 11px;
    }
    /* The caption takes one of the clamped lines. */
    #sheet-explore #query-table td.prose { grid-column: 1 / -1; -webkit-line-clamp: 4; }
}

/* Short landscape's split (css/sheet.css): the solve page's banner,
   pill and panels in it. */
@media (orientation: landscape) and (max-height: 500px) {
    /* The banner narrates a solve over the stage, as in portrait —
       never over the panel's handle and the input the solve came from. */
    body.sheet-open #status { right: calc(50% + 12px); }
    /* Centered in the safe part of the left half: the notch may sit on
       this side. */
    body.sheet-open:not(.hide-transport) #transport-pill {
        left: calc(25% + env(safe-area-inset-left, 0px) / 2);
        bottom: calc(var(--tabbar-h) + 8px);
        max-width: calc(50vw - 16px
            - env(safe-area-inset-left, 0px));
    }
    /* The panels sit on the right: only the right inset can reach them. */
    #sheet-moves { padding-left: 8px; }
    #sheet-explore { padding-left: 0; }
    #sheet-puzzle {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        align-content: start;
        column-gap: 12px;
        padding-right: calc(12px + env(safe-area-inset-right, 0px));
        padding-left: 12px;
    }
    #sheet-puzzle .group-heading { margin: 2px 0; }
    #pieces-group,
    #solution-group,
    #ui-switch-link {
        grid-column: 1 / -1;
    }
    /* Pieces: the preset select beside Reflect, the ID input beside
       Solve; the format hint yields to the input's placeholder. */
    #pieces-group {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: 3px;
    }
    #pieces-group > .group-heading,
    #pieces-group > .input-row {
        grid-column: 1 / -1;
    }
    #pieces-group > .group-heading { grid-row: 1; }
    #pieces-group > select {
        grid-row: 2;
        min-height: 44px;
        margin-top: 0;
    }
    #pieces-group > .hint-row {
        display: block;
        grid-column: 2;
        grid-row: 2;
        margin-top: 0;
    }
    #pieces-group > .input-row {
        grid-row: 3;
        margin-top: 0;
    }
    #pieces-group .hint { display: none; }
    #sheet-puzzle #ui-switch-link { margin-top: 4px; }
    #sheet-puzzle #mobile-puzzle-summary { display: none; }
    /* A landscape topbar shows every name whole, and the half-height
       panel has no room to repeat it. */
    #sheet-puzzle #mobile-puzzle-name { display: none; }
    #sheet-puzzle #view-mode-seg,
    #sheet-puzzle #rotate-cluster { gap: 3px; }
    /* A 667-wide phone leaves a mode button ~72px: "Transparent" needs
       the width the shared 10px padding would take. */
    #sheet-puzzle #view-mode-seg .btn { padding-left: 4px; padding-right: 4px; }
    #sheet-puzzle #rotate-cluster { grid-template-columns: repeat(3, 1fr); }
}

/* ── Piece picker: full-width panel above the tab bar ── */
/* Embedded mode skips the drawer's inline anchor positioning; the
   !important guards against any future inline writes regardless. */
#piece-picker {
    left: calc(8px + env(safe-area-inset-left, 0px)) !important;
    right: calc(8px + env(safe-area-inset-right, 0px)) !important;
    bottom: calc(var(--tabbar-h) + 8px) !important;
    top: auto !important;
    width: auto;
    height: min(440px, 55vh);
    height: min(440px, 55dvh);
    max-height: calc(100vh - var(--topbar-h) - var(--tabbar-h) - 16px);
    max-height: calc(100dvh - var(--topbar-h) - var(--tabbar-h) - 16px);
}
#piece-picker .piece-picker-heading { padding: 4px 6px 0; }
#piece-picker .piece-picker-heading strong { font-size: 14px; }
#piece-picker .piece-picker-search {
    flex: none;
    min-height: 40px;
    box-sizing: border-box;
}
#piece-picker .piece-picker-list { flex: 1; max-height: none; }
#piece-picker .piece-picker-list button {
    grid-template-columns: 64px minmax(0, 1fr) 24px;
    min-height: 62px;
    padding: 7px 8px;
}
#piece-picker .piece-picker-icon { width: 64px; height: 42px; }
#piece-picker .piece-picker-copy strong { font-size: 14px; }
#piece-picker .piece-picker-name { font-size: 11px; }

#sheet-explore #query-table td,
#sheet-explore #query-table th,
#sheet-moves .move-item,
#puzzle-info {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}
