/*
 * Relay at 390px — the narrow end of the same build.
 *
 * The design system's mobile frames (Claude Design pages 8–11) are 390px
 * content columns, not device mockups: "the same markup reflows from 390 to
 * 1440". So this file adds no screens and no second template tree. It restyles
 * what is already there, and reveals the handful of narrow-only components
 * defined — switched off — at the end of relay-components.css.
 *
 * EVERY RULE IN THIS FILE LIVES INSIDE `@media (max-width: 820px)`.
 * That is not a convention, it is the guarantee: MobileShellIsolationTests
 * parses this file and fails the build if a single top-level block is anything
 * else. It is what lets a whole mobile pass land without anyone having to
 * re-check the wide layout by eye.
 *
 * 820px is the breakpoint the rest of the system already uses. The blocks are
 * split by subject rather than merged into one, so a rule can be found by what
 * it is about; they are all the same query.
 *
 * Loaded last, so overrides win on order and need no specificity games.
 */

/* =========================================================================
   The shell — topbar collapses to one row, the tab bar takes over the nav
   ========================================================================= */

@media (max-width: 820px) {
    :root {
        /* The tab bar's own height, so everything that has to clear it —
           the page, the toasts, a sticky action bar — agrees on one number.

           80, not 64. 64 was the sum of the padding and a tab's `min-height`,
           but the Create tab is a 36px FAB above a label, which makes a tab 58px
           and the bar 79: every consumer of this token was ~15px short, so the
           tab bar has been covering the bottom 15px of every narrow screen. The
           number is now imposed on `.tabbar` below rather than describing it, so
           the two cannot disagree again — which is the whole point of the token. */
        --tabbar-h: 80px;
        --tabbar-clear: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
    }

    .tabbar {
        display: grid;
        /* `--tabbar-clear`, not `--tabbar-h`: the safe-area inset is part of the
           bar's box, which is why the padding below already adds it. */
        height: var(--tabbar-clear);
    }

    /* Nothing may end up underneath the tab bar. */
    body {
        padding-bottom: var(--tabbar-clear);
    }

    /* One 54px row: back-or-mark, the screen's name, search, avatar. The wide
       topbar wrapped instead, which on a phone became three or four stacked
       rows of chrome above a sticky header. */
    .topbar {
        flex-wrap: nowrap;
        gap: var(--s2);
        height: 54px;
        padding: 0 var(--s3);
    }

    /* The four navpills are the tab bar's job now; the approval count moves to
       the More tab; the theme switch and sign-out move into the More sheet,
       which is where 11e's settings index puts them. Scoped to the topbar, or
       this would hide the copies the sheet itself renders. */
    .topbar__nav,
    .topbar__end .theme-toggle,
    .topbar__signout,
    .topbar__end .badge-count {
        display: none;
    }

    /* The sheet gives it a whole row, so it can be thumb-sized. */
    .theme-toggle--sheet {
        margin-left: auto;
    }

    .theme-toggle--sheet button {
        width: 44px;
        height: 36px;
    }

    /* The wordmark goes; the mark alone still gets you home. */
    .topbar__mark {
        flex: none;
        gap: 0;
        font-size: 0;
    }

    .topbar__back {
        display: flex;
    }

    /* A screen with a back chevron has already said where it is. */
    .topbar__back ~ .topbar__mark {
        display: none;
    }

    .topbar__screen {
        display: block;
        overflow: hidden;
        flex: 1;
        white-space: nowrap;
        text-overflow: ellipsis;
    }

    .topbar__screensub {
        display: block;
        margin-top: 2px;
        font-family: var(--font-data);
        font-size: 10.5px;
        font-weight: 400;
        line-height: 1.3;
        letter-spacing: 0;
        color: var(--ink-3);
    }

    .topbar__searchbtn,
    .topbar__action {
        display: flex;
    }

    /* An editor's context bar was a crumb, a one-item "segmented control" and
       the save buttons — all three of which the narrow shell has somewhere
       better: the topbar says where you are, the topbar action holds History,
       and the pinned footer holds the saves. Mockups 10a and 10k draw no
       context bar on either editor. */
    .contextbar--editor {
        display: none;
    }

    /* Collapsed to the button above, and expanded over the row while it has
       focus — which is the same state ⌘K puts it in. relay.js sets
       `data-searching` so the field is genuinely out of the tab order until
       it is wanted, rather than sitting there invisible. */
    .topbar__search {
        display: none;
    }

    body[data-searching] .topbar__search {
        position: absolute;
        z-index: 1;
        right: var(--s3);
        left: var(--s3);
        display: flex;
    }

    body[data-searching] .topbar__mark,
    body[data-searching] .topbar__back,
    body[data-searching] .topbar__screen,
    body[data-searching] .topbar__searchbtn {
        visibility: hidden;
    }

    .searchbox {
        height: 38px;
    }

    /* The ⌘K hint is a lie on a phone. */
    .kbd {
        display: none;
    }

    .topbar__end {
        gap: var(--s2);
    }

    .avatar {
        width: 36px;
        height: 36px;
        font-size: 12px;
    }

    .toasts {
        bottom: calc(var(--tabbar-clear) + var(--s2));
    }
}

/* =========================================================================
   Context bar — the sub-nav becomes the mockups' segmented switcher
   ========================================================================= */

@media (max-width: 820px) {
    /* The qualifier in a label that only fits on a wide screen: "Core
       Articles" → "Articles", "People & roles" → "People". Its only rule is
       this one — everywhere else it is an ordinary inline span, which is what
       a wide screen wants. */
    .wide-only {
        display: none;
    }

    .contextbar {
        gap: var(--s2);
        padding: 9px var(--s3);
    }

    /* The crumb named the section; the topbar does that now. */
    .contextbar__crumb,
    .contextbar__divider {
        display: none;
    }

    /* Library ›, Create › and Settings › ship as a row of chips. At this width
       they are the Write · Sources · Outputs control the mockups draw: equal
       shares of one full-width row, no horizontal scroll. `.spacer` is what
       breaks the line, so whatever follows starts a row of its own. */
    .subchip {
        flex: 1 1 0;
        min-width: 0;
        min-height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: var(--r-md);
        font-size: 12.5px;
        text-align: center;
    }

    .subchip--out {
        flex: 1 1 100%;
    }

    .contextbar .spacer {
        flex: 1 0 100%;
        height: 0;
    }

    .seg {
        display: flex;
        width: 100%;
    }

    .seg__item {
        flex: 1;
        min-height: 36px;
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;
    }

    /* The section's action gets its own full-width row under the switcher,
       whether the partial wraps it in `.contextbar__actions` or drops it
       straight into the bar (the three nav partials do the latter). */
    .contextbar__actions {
        flex: 1 1 100%;
    }

    .contextbar__actions .btn,
    .contextbar > .btn,
    .contextbar > form,
    /* `.cued` pairs a callout with its control (see relay-components.css). The
       callouts are hidden down here, but the wrapper is still in the DOM, and a
       child combinator does not see through it — so these have to name it or a
       wrapped button stops stretching on a phone. Not narrow polish for the
       tutorial: it is keeping the narrow shell exactly as it was. */
    .contextbar > .cued,
    .contextbar > .cued > .btn {
        flex: 1;
    }

    .contextbar > form .btn,
    .contextbar > .cued > form .btn {
        width: 100%;
    }

    .calnav {
        flex: 1 1 100%;
    }

    .calnav__label {
        flex: 1;
    }
}

/* =========================================================================
   Dialogs — every drawer and modal becomes a bottom sheet
   -------------------------------------------------------------------------
   One block converts all nine choosers, every confirm, the history drawer and
   the Tighten preview at once, with no template changes: on a phone a dialog
   comes up from the thumb, not out of the middle of the screen.
   ========================================================================= */

@media (max-width: 820px) {
    /* A sheet covers the chrome it sits over, so the scrim does too. */
    .scrim,
    body:has(.contextbar) .scrim {
        inset: 0;
    }

    .modal {
        place-items: end stretch;
        padding: 0;
    }

    .modal__card,
    .drawer {
        width: 100%;
        max-width: none;
        max-height: 92vh;
        padding-bottom: env(safe-area-inset-bottom);
        border: 0;
        border-radius: var(--r-lg) var(--r-lg) 0 0;
        box-shadow: 0 -10px 30px rgba(22, 24, 43, .18);
        animation: sheet-up .22s var(--ease);
    }

    .drawer {
        top: auto;
        right: 0;
        bottom: 0;
        left: 0;
    }

    /* The grab handle every sheet in the mockups has. */
    .modal__card::before,
    .drawer::before {
        content: "";
        flex: none;
        width: 34px;
        height: 4px;
        margin: 10px auto var(--s1);
        border-radius: var(--r-pill);
        background: var(--line-strong);
    }

    /* The one exception: the states gallery renders its confirms in place
       rather than as overlays, so they are cards, not sheets. */
    .modal__card--static {
        max-height: none;
        border: 1px solid var(--line-strong);
        border-radius: var(--r-lg);
        box-shadow: var(--shadow-1);
        animation: none;
    }

    .modal__card--static::before {
        content: none;
    }

    .modal__foot,
    .drawer__foot {
        padding-bottom: 18px;
    }

    /* Two actions side by side get a thumb-sized row; the primary leads. */
    .modal__foot .btn,
    .sheet__foot .btn {
        flex: 1;
        min-height: 48px;
    }

    /* The Core Article picker is its own overlay shape — a grid of card plus
       rail, not a `.modal__card` — so the sheet treatment above misses it.
       Releasing its height was wrong twice over: it is what stopped the rail's
       explanatory panels from being clipped, and without it they spilled down
       the page underneath the picker.
       Here the *form* is the sheet: it scrolls, the card and the rail scroll
       inside it as one document, and the foot with the count and the Attach
       button stays pinned to the bottom of it. */
    .artpick {
        width: 100%;
        max-width: none;
        max-height: 92vh;
        gap: 0;
        padding-bottom: env(safe-area-inset-bottom);
        border-radius: var(--r-lg) var(--r-lg) 0 0;
        background: var(--surface);
        box-shadow: 0 -10px 30px rgba(22, 24, 43, .18);
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    .artpick::before {
        content: "";
        width: 34px;
        height: 4px;
        margin: 10px auto var(--s1);
        border-radius: var(--r-pill);
        background: var(--line-strong);
    }

    /* No longer a card floating on a scrim — it is the top of the sheet.
       `overflow: hidden` has to go with it: it makes the card its own scroll
       container, and a sticky foot inside one is pinned to *that* rather than
       to the sheet, which is the same as not being pinned at all. */
    .artpick__card {
        max-height: none;
        border: 0;
        border-radius: 0;
        box-shadow: none;
        overflow: visible;
    }

    /* The list grows with the sheet instead of scrolling inside it; two nested
       scrollers on a phone is a thing nobody can aim at. */
    .artpick__list {
        overflow-y: visible;
    }

    .artpick__foot {
        position: sticky;
        z-index: 1;
        bottom: 0;
    }

    .artpick__rail {
        max-height: none;
        overflow-y: visible;
        padding: var(--s4) var(--s4) var(--s5);
        background: var(--surface-2);
        border-top: 1px solid var(--line);
    }

    /* The selection tick. Its offsets are drawn for the 15px box, so the 20px
       fingertip target above would leave it sitting in the top-left corner —
       centring it makes it independent of the box's size. */
    .selectbox {
        display: grid;
        place-content: center;
    }

    .selectbox:checked::after {
        width: 5px;
        height: 10px;
        margin: -2px 0 0 0;
    }

    /* Declared inside the query because it is only ever used inside it, and
       because a top-level block here would break the isolation test that
       makes this file's promise checkable. `prefers-reduced-motion` in
       relay-base.css already switches it off for anyone who asked. */
    @keyframes sheet-up {
        from {
            transform: translateY(12%);
            opacity: 0;
        }
    }
}

/* =========================================================================
   Listings — every table becomes a card list, so nothing scrolls sideways
   ========================================================================= */

@media (max-width: 820px) {
    .table-wrap {
        overflow-x: visible;
    }

    table.listing {
        display: block;
        min-width: 0;
    }

    table.listing thead {
        display: none;
    }

    table.listing tbody {
        display: block;
    }

    /* Each row is a card, and its cells are flex items in it. Which cell goes
       where is decided by a class, not by position: a listing's first column
       is a checkbox here, a status pill there, a health dot somewhere else. */
    table.listing tbody tr {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0 var(--s2);
        margin-bottom: var(--s3);
        padding: var(--s3) 14px;
        border: 1px solid var(--line);
        border-radius: var(--r-lg);
        background: var(--surface);
        box-shadow: var(--shadow-1);
    }

    /* A cell gets its own line by default — a card is read down, not across. */
    table.listing tbody td {
        display: flex;
        flex: 1 1 100%;
        align-items: baseline;
        gap: var(--s3);
        padding: 3px 0;
        border: 0;
    }

    /* The column header, carried on the cell, becomes the row's label. Cells
       that name themselves — the headline, the actions — carry no data-label
       and so get no prefix. */
    table.listing tbody td[data-label]::before {
        content: attr(data-label);
        flex: none;
        min-width: 84px;
        font-family: var(--font-ui);
        font-size: 10.5px;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--ink-3);
    }

    /* The headline, and whatever narrow marker leads it — a select box, a
       health dot — sharing the card's first line. */
    table.listing tbody td.lead {
        display: block;
        flex: 1 1 auto;
        margin-bottom: var(--s1);
        padding-bottom: var(--s2);
        border-bottom: 1px solid var(--line);
    }

    table.listing tbody td.pick {
        flex: none;
        margin-bottom: var(--s1);
        padding-bottom: var(--s2);
    }

    table.listing tbody td.num {
        text-align: left;
    }

    /* Actions go full width at the foot of the card, thumb-sized. */
    table.listing tbody td.actions {
        flex-wrap: wrap;
        gap: var(--s2);
        margin-top: var(--s2);
        padding-top: var(--s3);
        border-top: 1px solid var(--line);
    }

    table.listing tbody td.actions .btn {
        flex: 1 0 auto;
        min-height: 40px;
    }

    /* An empty state is a message about the whole listing, not a card in it.
       The agenda's day headers also span every column, so they are excluded
       explicitly — they are a card's heading, not the absence of cards. */
    table.listing tbody tr:not(.agenda__day) td[colspan] {
        display: block;
        flex: 1 1 100%;
        margin: 0;
        padding: 0;
        border: 0;
    }

    table.listing tbody tr:not(.agenda__day):has(td[colspan]) {
        display: block;
        margin: 0;
        padding: 0;
        border: 0;
        background: none;
        box-shadow: none;
    }

    /* The day header itself: one row, spanning the cards it introduces. */
    table.listing tbody tr.agenda__day td {
        flex: 1 1 100%;
        padding: 0;
        border: 0;
        font: inherit;
        color: inherit;
    }

    .pagination {
        flex-wrap: wrap;
        gap: var(--s2);
    }

    /* --- The Base Pieces listing (mockup 10p) -----------------------
       The table gives way to 10p's rows. A swap rather than a restyle: 10p's
       row is a title, one meta line and the coverage strip, where the table
       has six columns, and no CSS makes six cells read as three lines — see
       relay/partials/piece_rows.html for the two attempts that proved it. */
    .prows {
        display: flex;
    }

    .table-wrap--wide {
        display: none;
    }

    /* 10o's row is something you tick, so the whole row is the target and the
       tick sits at its head — level with the title, not floating in the middle
       of a three-line row. */
    .prows--pick .prow {
        align-items: flex-start;
        cursor: pointer;
    }

    .prows--pick .selectbox {
        margin-top: 2px;
    }

    .prows--pick .prow__chev {
        align-self: center;
    }
}

/* =========================================================================
   Layout — every split, grid and editor comes down to one column
   ========================================================================= */

@media (max-width: 820px) {
    .page {
        padding: 18px var(--s4) 26px;
    }

    .page--flush > .banner {
        margin: var(--s3) var(--s4) 0;
    }

    .page__title {
        font-size: 22px;
    }

    /* The Base Piece title renders at display scale, which overflows its own
       box at 390px — the text ran past the input's right edge rather than
       wrapping. A notch down fits, and it is still unmistakably the title. */
    .input--title {
        font-size: 19px;
    }

    /* `.split` already wraps on flex-basis, but the rail keeps its pinned
       width once wrapped — `flex-grow: 0` is deliberate on a wide screen and
       wrong here, where a 300px rail under a 358px column reads as a mistake.
       Both halves take the whole width instead. */
    .split__main,
    .split__rail {
        flex: 1 1 100%;
    }

    /* These three are grids, so they do not wrap at all. */
    .split3,
    .editor,
    .grid-3--set {
        grid-template-columns: minmax(0, 1fr);
    }

    /* --- One pane at a time (mockups 10a–10c, 10d) -------------------
       The switcher appears, and only the pane it points at is shown. Every
       pane stays in the document — a form that spans two of them still posts
       both, and switching costs nothing. */
    .paneswitch {
        display: flex;
        position: sticky;
        z-index: var(--z-sticky);
        top: 54px;
        margin: calc(-1 * 18px) calc(-1 * var(--s4)) var(--s4);
    }

    [data-pane]:not([data-pane-on]) {
        display: none;
    }

    /* `order` was how the text got to the top when the three panes stacked.
       With one pane showing there is nothing to reorder. */
    .split3__main {
        order: 0;
    }

    .editor__rail {
        border-top: 1px solid var(--line);
        border-left: 0;
    }

    .editor__main,
    .editor__rail {
        padding: 18px var(--s4);
    }

    .editor {
        min-height: 0;
    }

    .master-detail {
        flex-direction: column;
    }

    /* 420px of minimum track on a 390px screen is the one place the wide
       layout still forced a horizontal scroll. */
    .grid-approvals {
        grid-template-columns: minmax(0, 1fr);
    }

    .grid-2,
    .grid-3 {
        grid-template-columns: minmax(0, 1fr);
    }

    /* The stat tiles stay two up: they are a figure and a short label, and one
       per row turns Today's four counts into most of a screen of scrolling. */
    .grid-4 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* Two up, which is what the mockup's media grid is. */
    .thumbs--media {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .filterbar {
        padding: var(--s3) var(--s4);
    }

    .filterbar .field {
        max-width: none;
        flex: 1 1 140px;
    }

    /* A label and its figure on one baseline, where the figure is a sentence —
       "3 keywords · matched 12 items" — stops fitting well before 390px. */
    .fieldhead,
    .pillar-group__head,
    .section-head,
    .gphbar {
        flex-wrap: wrap;
    }

    /* A listing's filters are one scrollable row, not four stacked ones —
       mockups 10p, 11b and 11c all draw a single strip of chips you swipe
       along. Wrapped, the Base Pieces filters alone were 200px of chrome
       above the first row.

       This is the one place a horizontal scroller is right: it is a short
       row of controls whose overflow is obvious and expected, not content
       that would be lost off-screen. */
    .toolbar {
        flex-wrap: nowrap;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        padding-bottom: var(--s1);
    }

    .toolbar::-webkit-scrollbar {
        display: none;
    }

    .toolbar > * {
        flex: none;
    }

    /* The search field leads and keeps a usable width; `.spacer` inside a
       scroller would otherwise stretch to infinity. */
    .toolbar .searchbox {
        width: min(58vw, 250px);
    }

    .toolbar .spacer {
        display: none;
    }

    /* `flex: none` keeps these at max-content, which is right beside a label
       in a 700px pane and is what pushed the Pillars form past the viewport:
       "comma-separated · substring match, case-insensitive" is a sentence, and
       at 390px it has to be allowed to become two lines. */
    .fieldhead__count,
    .pillar-group__name,
    .contextbar__count {
        flex: 0 1 auto;
        min-width: 0;
        line-height: 1.4;
    }
}

/* =========================================================================
   Touch — 44px targets, and inputs iOS will not zoom into
   ========================================================================= */

@media (max-width: 820px) {
    /* Under 16px, iOS Safari zooms the page on focus and never zooms back. */
    input,
    select,
    textarea,
    .richtext__surface {
        font-size: 16px;
    }

    .btn {
        min-height: 44px;
    }

    /* The rail's block buttons read as list items on a wide screen, which is why
       `.btn--block` sets `justify-content: flex-start`. At this width their
       labels wrap, and a wrapped label pinned left in a full-width primary
       button is exactly the complaint. */
    .btn--block {
        justify-content: center;
    }

    .btn--sm {
        min-height: 38px;
    }

    /* The channel row becomes a summary card: name and cadence on one line,
       the spec chips under them. */
    .listrow__specs {
        display: flex;
    }

    .listrow {
        flex-wrap: wrap;
        align-items: center;
        padding: var(--s3) var(--s3);
    }

    /* `min-height` has to be paired with a centring display, or the extra
       height is simply added below the text: as a flex item an inline box
       blockifies, and nothing distributes the space. This is what put the
       labels hard against the top of the Pulse and Graph pills. `.subchip` and
       `.seg__item` above already pair the two — these did not.

       `.listrow` is already `display: flex; align-items: center`. */
    .pilltoggle,
    .calnav__step,
    .richtext__btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 44px;
    }

    .listrow {
        min-height: 44px;
    }

    /* A `<select>` must not become a flex container — the UA draws its own box
       and centres the value itself. Padding is how you make one thumb-sized. */
    .pillselect {
        padding-top: 12px;
        padding-bottom: 12px;
    }

    .calnav__step {
        min-width: 44px;
    }

    /* The pickers' checkbox, at fingertip size. */
    .selectbox {
        width: 20px;
        height: 20px;
    }

    /* A row's text actions — Open, Edit, Retry, Place. They are links by
       design (the mockups draw them as links, not buttons) and that is worth
       keeping, but a 17px line box is not something you can hit with a thumb.
       Padding rather than height, so they stay on the baseline they share with
       the rest of the row. */
    .linkbtn,
    .ttl {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
    }

    /* These four are already `display: flex` and already say how they align —
       `.runrow` and `.statrow` are `space-between` label-left/value-right rows
       on `align-items: baseline`. Making them `inline-flex` shrink-wrapped them
       to max-content, which left `space-between` no free space to distribute,
       so the value stopped sitting at the panel's right edge. They want the
       height and nothing else. */
    .runrow,
    .statrow,
    .dotrow,
    .failrow__what {
        min-height: 40px;
    }

    /* A control whose visible size is the point — a 20px tick, a 14px ✕ —
       gets its touch area from a pseudo-element instead, so the thing you can
       hit is 44px while the thing you can see is unchanged. */
    .selectbox,
    .token__remove,
    .topbar__mark {
        position: relative;
    }

    .selectbox::before,
    .token__remove::before,
    .topbar__mark::before {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: 44px;
        height: 44px;
        transform: translate(-50%, -50%);
    }

    /* `.selectbox` draws its tick in `::after`, so `::before` is free; but it
       is also `display: grid` here, which would lay the pseudo-element out as
       a cell. Taking it out of flow keeps it a hit area and nothing else. */
    .selectbox::before {
        position: absolute;
    }

    select.select,
    input[type="checkbox"]:not(.selectbox),
    input[type="radio"] {
        min-height: 24px;
        min-width: 24px;
    }

    /* Those touch targets are *taller* than the label's line box, so the wide
       pass's downward nudge (`.check input`, relay-components.css) now pushes
       the box below its own text rather than onto it. Same reasoning, other
       direction: half the difference between the line and the box — which is a
       different number for the two, because a plain checkbox grows to 24px here
       and `.selectbox` to 20px. */
    .check input:not(.selectbox) {
        margin-block-start: -2.5px;
    }

    .check .selectbox {
        margin-block-start: -1.5px;
    }

    /* `.check--plain` sets a smaller type, so its line is shorter still and the
       same 24px box wants a little more lift. */
    .check--plain input:not(.selectbox) {
        margin-block-start: -3.5px;
    }
}

/* =========================================================================
   Sticky action bar — the primary action never sits in a scroll
   -------------------------------------------------------------------------
   Opt-in: a screen adds `.actionbar` to the footer row it already had. There
   is no wide-screen counterpart, because on a wide screen the row is already
   in view.
   ========================================================================= */

@media (max-width: 820px) {
    .actionbar {
        display: flex;
        position: sticky;
        z-index: var(--z-sticky);
        right: 0;
        /* Above the tab bar, not under it. `sticky` resolves against the
           scrollport — the viewport — and not against the body's padding box,
           so `bottom: 0` would park it behind the tabs. */
        bottom: var(--tabbar-clear);
        left: 0;
        display: flex;
        gap: 9px;
        margin: var(--s4) calc(-1 * var(--s4)) 0;
        padding: 11px var(--s4) var(--s4);
        border-top: 1px solid var(--line);
        background: var(--surface);
        box-shadow: 0 -6px 18px rgba(22, 24, 43, .06);
    }

    /* `body`'s bottom padding already clears the tab bar, so sticking to
       `bottom: 0` lands the bar directly on top of it rather than under it. */

    .actionbar .btn {
        flex: 1;
        min-height: 48px;
    }

    /* The one that matters gets the wider share, as every mockup draws it. */
    .actionbar .btn--primary {
        flex: 1.3;
    }

    /* 10l closes its foot with the consequence of the two buttons above it. */
    .actionbar--noted {
        flex-wrap: wrap;
    }

    .actionbar__note {
        flex: 1 1 100%;
        font-family: var(--font-data);
        font-size: 10.5px;
        line-height: 1.4;
        text-align: center;
        color: var(--ink-3);
    }

    /* 10o stacks its foot: a choice about the run, then the run. */
    .actionbar--stack {
        flex-direction: column;
        align-items: stretch;
        gap: var(--s2);
    }

    .actionbar--stack .btn {
        flex: none;
    }

    /* Inside an edge-to-edge editor there is no page padding to cancel. */
    .page--flush .actionbar,
    .editor__main .actionbar {
        margin-left: 0;
        margin-right: 0;
    }
}

/* =========================================================================
   Calendar (mockups 9a–9f)
   ========================================================================= */

@media (max-width: 820px) {
    /* The month keeps its shape — that is the whole point of a month — but a
       45px cell cannot hold a title, so each output becomes its status dot.
       Mockup 9b. */
    .cal {
        gap: 2px;
        grid-auto-rows: minmax(52px, auto);
    }

    .cal__day {
        min-height: 0;
        padding: var(--s1);
    }

    /* The chip keeps its status colour and loses its words: in a seven-across
       grid a cell is 45px, which cannot hold "LinkedIn · 09:00", and 9b draws
       dots instead. The status moves from the left border onto the whole dot.
       Nothing is lost — the chip still opens its popover, and the `title` it
       already carries still names it in full.

       Only in the seven-across grids. The week view stacks to one day per row
       at this width, so there a chip has the whole screen and stays a chip —
       reducing it to a dot there was throwing away the space that stacking had
       just bought. */
    /* The dot is *painted* into a 20px box rather than being one. 9b draws a
       7px dot, which is a fine mark and an impossible button — and this button
       opens the output's popover. A transparent hit area hung off it as a
       pseudo-element does not survive what the cell paints on top (the date
       number sits right above), so the box is real and the dot is a gradient.

       20px is the ceiling, not a preference: a cell in a seven-across grid at
       390px is 49px wide, and this is what fits with the wrapping below.

       `--dot` carries the status colour, so each modifier stays one line. */
    .cal:not(.cal--week) .cal-chip {
        --dot: var(--ink-3);
        width: 20px;
        height: 20px;
        padding: 0;
        border: 0;
        border-radius: 50%;
        background: radial-gradient(
            circle at 50% 50%, var(--dot) 3.5px, transparent 3.5px
        );
        /* Collapsed rather than clipped: `overflow: hidden` would take the hit
           area with it, and the `title` still names the output in full. */
        font-size: 0;
    }

    .cal:not(.cal--week) .cal-chip--scheduled {
        --dot: var(--marigold);
    }

    .cal:not(.cal--week) .cal-chip--posted {
        --dot: var(--posted);
    }

    /* The cell is already outlined dashed marigold by `.cal__day--gap`, which
       is 9b's whole treatment for a gap day. A second marker would be noise. */
    .cal-chip--gap {
        display: none;
    }

    /* Chips are direct children of the cell, so the cell is what lays them
       out: a wrapping row of dots under the date. */
    .cal:not(.cal--week) .cal__day {
        flex-flow: row wrap;
        align-content: flex-start;
        /* 2px, because the dots are 20px targets now and this is the gap that
           still lets two sit on a line in a 49px cell. A third wraps, and the
           week's row grows to take it. */
        gap: 2px;
    }

    .cal:not(.cal--week) .cal__date {
        flex: 1 0 100%;
        font-size: 12px;
    }

    /* A week is seven days of detail — it stacks rather than shrinking, one
       day per row, each keeping its weekday name and its real chips. */
    .cal--week {
        grid-template-columns: minmax(0, 1fr);
        grid-auto-rows: auto;
        gap: var(--s2);
    }

    .cal--week .cal__day {
        min-height: 0;
        padding: 11px 12px;
    }

    .cal--week .cal__date {
        font-size: 12.5px;
        font-weight: 600;
        color: var(--ink);
    }

    /* The column header belongs to a seven-across grid. Once the week has
       stacked, "MON TUE WED…" sits above a list whose rows it no longer
       labels — seven headings for one column. `:has` scopes this to the week's
       own header and leaves the month's, which still lines up. */
    .cal__weekdays:has(+ .cal--week) {
        display: none;
    }

    .cal--mini .cal__day {
        min-height: 0;
    }

    /* The list view is the agenda (9a): a day header, then its outputs. Both
       header kinds are in the wide markup too, and hidden there. */
    .agenda__day,
    .agenda__gap {
        display: flex;
        align-items: center;
        gap: 9px;
        margin: 0 0 var(--s2);
        padding: 11px 14px;
        border: 1px solid var(--line);
        border-radius: var(--r-md);
        background: var(--surface-2);
        font-family: var(--font-ui);
        font-size: 12px;
        font-weight: 700;
        line-height: 1;
        color: var(--ink-2);
    }

    .agenda__day--today {
        border-color: color-mix(in srgb, var(--signal) 25%, transparent);
        background: var(--signal-tint);
        color: var(--signal);
    }

    /* A gap is a row you can act on, not an absence — 9a's whole argument for
       the agenda over a grid. */
    .agenda__gap {
        border-color: color-mix(in srgb, var(--marigold) 30%, transparent);
        background: var(--marigold-tint);
        font-weight: 600;
    }

    .agenda__count {
        margin-left: auto;
        font-family: var(--font-data);
        font-size: 11px;
        font-weight: 400;
        color: var(--ink-3);
    }

    .agenda__day--today .agenda__count {
        color: var(--signal);
    }

    /* Four legend items and a tally in one nowrap row is the one thing on the
       calendar that still pushed the page sideways. */
    .cal__legend {
        flex-wrap: wrap;
        gap: var(--s2) var(--s3);
    }

    .cal__legend .num {
        flex-basis: 100%;
    }
}

/* =========================================================================
   Content graph (mockup 11d) — the canvas gives way to the lineage column
   ========================================================================= */

@media (max-width: 820px) {
    .gphwrap,
    .gph__legend {
        display: none;
    }

    .lineage {
        display: flex;
    }

    .gphpanel {
        padding: var(--s4);
    }
}

/* =========================================================================
   Screen-specific corrections
   ========================================================================= */

@media (max-width: 820px) {
    /* Today's "Needs you now" rows carry four things — a severity glyph, the
       text, a status pill and the action. Two grid columns cannot hold that:
       the pill lands in the 26px glyph track, overflows it, and the action
       lands on top of what has spilled out.

       Flex instead, so the row wraps where it needs to: glyph and text on the
       first line, then the pill and the action together on the second, indented
       to the text's edge. Nothing overlaps and nothing is truncated. */
    .attention {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--s2) var(--s3);
        padding: 13px 14px;
    }

    .attention__ic {
        flex: none;
    }

    /* The basis is what forces the wrap. `flex: 1 1 0` let the text shrink to
       share the line with the pill and the action instead, which squeezed the
       title to one word per line — the opposite failure to the overlap. Asking
       for the whole line minus the glyph means the other two cannot fit beside
       it and drop to the next one. */
    .attention__text {
        flex: 1 1 calc(100% - 22px - var(--s3));
        min-width: 0;
    }

    /* Both sit on the second line, sharing it, lined up under the title. */
    .attention .pill {
        flex: none;
        margin-left: calc(22px + var(--s3));
    }

    .attention .btn {
        flex: none;
        margin-left: auto;
    }

    /* The output editor's two media slots stack (already true at 620px) and
       its preview rail follows the copy. */
    .slots {
        grid-template-columns: minmax(0, 1fr);
    }

    /* An approval card carries a diff, so it needs the full width. */
    .grid-approvals > * {
        min-width: 0;
    }

    /* Swipe-to-approve: the card slides to uncover the action behind it.
       Additive — the Approve and Send back buttons are still there, which is
       what keeps a gesture from being the only way to do anything. */
    .swipe {
        position: relative;
        overflow: hidden;
        border-radius: var(--r-lg);
    }

    .swipe__action {
        position: absolute;
        inset: 0;
        /* Switched on here — `display: none` is its base state, or the labels
           print above the card on a wide screen. */
        display: flex;
        align-items: center;
        gap: 9px;
        padding: 0 18px;
        font-family: var(--font-ui);
        font-size: 14px;
        font-weight: 600;
        color: var(--pri-on);
    }

    .swipe__action--go {
        justify-content: flex-start;
        background: var(--posted);
    }

    .swipe__action--back {
        justify-content: flex-end;
        background: var(--critical);
    }

    .swipe__card {
        position: relative;
        background: var(--surface);
        touch-action: pan-y;
    }

    .swipe__card--settling {
        transition: transform .18s var(--ease);
    }

    /* The sign-in panel is the pitch, not the tool. */
    .signin__panel {
        display: none;
    }
}

/* =========================================================================
   Tap targets, second pass — what a 390px audit of every screen turned up
   ========================================================================= */

@media (max-width: 820px) {
    /* An audio row is a four-column grid: name, duration, date, note. Three of
       those are fixed, so at 390 the name — the only thing that says *which
       file this is* — was squeezed to nothing and ellipsised down to its ♫
       glyph. Same answer every listing gets here: the identifier takes a line
       of its own and the facts follow underneath. */
    .audiorow {
        display: flex;
        flex-wrap: wrap;
        gap: 5px var(--s3);
        padding: 12px var(--s3);
    }

    .audiorow__name {
        flex: 1 0 100%;
        min-height: 32px;
    }

    /* A keyword's ✕ was 8×12 — the only way to remove one, and not reachable
       with a thumb. The button grows into the token's padding rather than the
       glyph growing, so a row of keywords still reads as text. */
    .token__remove {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 32px;
        height: 32px;
        margin: -8px -10px -8px 0;
        font-size: 13px;
    }

    /* The second pill-shaped select. `.pillselect` (calendar, articles, graph)
       was given its height in the first pass; this one — the Base Pieces and
       Generate filter bars — is a different class doing the same job, and was
       missed. Padding rather than `min-height`, because a `<select>` draws its
       own box and must not become a flex container. */
    .select--pill {
        padding-top: 11px;
        padding-bottom: 11px;
    }

    /* The pillar chooser on a Core Article is a bare `<select>` inside a chip,
       with no class of its own — so it is reached through the chip. */
    .pillarchip select,
    .editor .select,
    .field .select {
        min-height: 44px;
    }

    /* 26px is narrow for a thumb even at the full 44px tall, and the toolbar
       has the room: seven buttons at 40px still fit a 390px column. */
    .richtext__btn {
        min-width: 40px;
    }

    /* Both are the action on the row they sit in — and Place… schedules a draft
       without a drag, which is the whole reason it exists on touch. */
    .dock__place,
    .banner__close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 40px;
    }

    /* A text-styled button is still a button. Width as well as height, because
       several of these are two or three characters ("All 9", "↺"). */
    .linkbtn,
    .pagination__page {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 40px;
    }

    /* Whole-row links in the rails: impact, revisions and "used in" are already
       flex, so the height costs nothing but the line it is given. */
    .impactrow,
    .revrow,
    .usedrow,
    .srow,
    .exprow {
        min-height: 40px;
    }

    /* These three are plain inline `<a>`s — a feed's name in the Pulse dock, a
       channel's name in the cadence panel, a rail's "see all". `min-height` is
       ignored on a non-replaced inline box, so it has to come with a display
       that honours it; that was the whole of the bug, and it is silent. */
    .dock__title,
    .cadence__name--link,
    .rail-more {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
    }

    /* A 20px checkbox is the control its whole row is about — bulk select on
       Generate, the source pickers. */
    .selectbox {
        width: 22px;
        height: 22px;
    }

    /* The logomark is a 20px glyph in a 54px bar; the anchor was the glyph. */
    .topbar__mark {
        display: flex;
        align-items: center;
        min-width: 40px;
        min-height: 44px;
    }

    /* The tutorial's on-screen guidance is a wide-screen feature, by decision:
       per Johanna, the guided tour is not being optimised for narrow and is
       hidden here rather than half-supported.

       The hub page at /getting-started/ stays — it is an ordinary page, it
       reflows below, and it is what the More sheet's Help row opens. So a phone
       gets the checklist and the "Do it" links; it does not get the strip under
       the context bar or the callouts beside the controls. `.gs__note--narrow`
       on the hub says so, rather than leaving somebody waiting for a bubble that
       is never coming. */
    .tutstrip,
    .cue {
        display: none;
    }

    /* The four stages become four rows, and the arrows point down the column
       they now describe rather than across a row that no longer exists.

       The stages have to give up their flex basis with the direction: `1 1 12rem`
       is a width across a row and a *height* down a column, so each card grew to
       192px of mostly empty space. */
    .loop {
        flex-direction: column;
    }

    .loop__stage {
        flex: 0 0 auto;
    }

    .loop__arrow {
        justify-content: center;
        transform: rotate(90deg);
    }

    .gs__note--narrow {
        display: block;
    }

    /* Each row's action drops under its text: a title, a sentence and two
       controls is more than one 390px row holds. */
    .steprow {
        flex-wrap: wrap;
    }

    .steprow__end {
        flex: 1 1 100%;
        justify-content: flex-end;
    }

}
