/**
 * Pawsies - UI layer for the rebuilt pages
 *
 * The design system shared by the home page and the feature pages: layout
 * tokens, the type contract, the card grids, the product plate, the buttons.
 * Loaded with $pageStyles, after tokens.css and base.css, so it only ever
 * adds - it restates no colour, radius or shadow that tokens.css already
 * names.
 *
 * WHY IT EXISTS
 *   These pages were built as gitignored workbenches with their CSS inline,
 *   which tools/check-css.php permits only because it skips git-ignored files.
 *   Promoting them meant the ratchet applied, and the ratchet is right: the
 *   home page and twelve feature pages sharing one cached sheet is the whole
 *   point of the seam. welcome.php came OFF the $LEGACY list on the way in.
 *
 * THE .pw- PREFIX
 *   Everything here is namespaced .pw-. It was .ht- while the pages were
 *   called hometest2.php, which stood for nothing once they became the home
 *   page; the rename happened at promotion rather than being left as a
 *   permanent artefact of where the work started. The blog listing uses .bl-
 *   in the same way and shares this system's values - the hairline, the
 *   eyebrow, the topic-family colours - without sharing this file yet.
 *
 * ONE SHEET, ON PURPOSE
 *   Every block in includes/components.php is styled here, whether or not the
 *   page you are looking at uses it. One cached request for the whole system
 *   beats three that each have to be reasoned about, and the split between
 *   "shared" and "page-specific" turned out not to be stable: the hero, the
 *   chip row and the split row all began as feature-page-only rules and are
 *   now blocks any page can open with.
 */

/* =====================================================================
   Home redesign - scoped to .pw so it can sit beside the live page.

   tokens.css and base.css are already loaded by includes/header.php, so
   nothing here restates a colour, a radius or the reset. This file only
   adds. The one thing it overrides is the heading face, and deliberately:
   base.css gives h1/h2/h3/h5 the Bogart serif, and the whole point of this
   direction is that headlines are sans.
   ===================================================================== */

/*
 * Layout tokens on BODY, not on .pw. The nav is a sibling of .pw, and a
 * custom property declared on .pw does not reach it - the nav-width override
 * at the foot of the page needs --pw-max and --pw-pad to resolve. Custom
 * properties inherit down; they do not leak across. Same trap the blog hit.
 */
body {
    --pw-max:  1440px;
    --pw-pad:  clamp(1.25rem, 3vw, 3rem);
    --pw-line: #EFE6DC;
    /* The band ground, used by the tour and the audience section. Named
       because two sections share it: as a literal in both, they were one
       careless edit away from being two nearly-identical colours, which is
       the failure that is invisible until someone screenshots them together.
       --cream-dark (#FFF5EC) is NOT this - it reads yellow beside the page's
       --cream; this is a touch pinker and a touch darker. Belongs in
       assets/css/tokens.css with a name if this direction ships. */
    --pw-band: #FBF5F0;
    /* Every section's vertical padding, top and bottom, one value. It was
       5.5rem top against 5rem bottom, written out at six call sites, and one
       of them had no bottom at all - which is how two sections ended up with
       their last row flush against the next ground. A section is a section;
       they all breathe the same. */
    --pw-gap: clamp(3.5rem, 7vw, 5.5rem);
    /* The site nav is fixed, 71px, z-index 1000. A rail stuck at top:0 slides
       underneath it and the two sets of text overlap. The script at the foot
       keeps this honest if the nav height ever changes. */
    --pw-nav:  71px;
}

/*
 * overflow-x: CLIP, not hidden. `hidden` makes the element a scroll container
 * and a scroll container silently kills position:sticky inside it, which is
 * what would stop the jump rail sticking. base.css sets `hidden` on body, so
 * this is a necessary override rather than a preference.
 */
html { overflow-x: clip; }
body { overflow-x: clip; }

.pw {
    /* The blog's five topic families, verbatim from blog.php, for the writing
       strip at the foot. The four above are the same four hues doing a second
       job; these keep the blog's own names so a card here and the same card on
       /blog are provably the same colour. */
    --fam-colony:  #E8830C;
    --fam-dogs:    #5E9E75;
    --fam-medical: #B4553F;
    --fam-small:   #8E77BE;
    --fam-general: #9A8F85;

    /*
     * The bullet tick, drawn rather than set in an icon font. Line Awesome's
     * la-check is available in the icon subset, but an icon font glyph
     * cannot be centred inside a disc reliably - the metrics are the font's,
     * not the artwork's - and it arrives with the rest of the subset. One path,
     * round caps and joins, stroke weight matched to DM Sans.
     *
     * Applied as a MASK, not a background image, so the colour still comes
     * from a token and a palette change reaches it. A data URI with the stroke
     * baked in would not.
     */
    --pw-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 12'%3E%3Cpath d='M1.8 6.3L5.9 10.2L14.2 1.8' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

    /* WHITE is the page. A section that wants another ground sets it itself
       and goes full-bleed to do so - .pw-tour and .pw-audience are the only
       two that do. Nothing here inherits a tint it did not ask for, which is
       what the cream ground was quietly doing to the masthead, the blog strip
       and the closing block. */
}

/* The page ground. On body rather than on .pw, so an overscroll or a short
   viewport does not reveal base.css's cream behind the page - and so a page
   that is NOT white can override it in its own stylesheet without .pw
   fighting back. blog.php does exactly that: it loads this sheet for the hero
   block and keeps its cream ground, because its inline <style> comes after
   the $pageStyles link. */
body { background: var(--white); }

.pw-wrap { max-width: var(--pw-max); margin: 0 auto; padding-inline: var(--pw-pad); }

/*
 * ONE Bogart on the page, and it is the masthead h1 - see .pw-masthead h1.
 *
 * Everything else is DM Sans, including every h2. base.css hands the serif to
 * h1/h2/h3/h5 site-wide, so this rule exists to TAKE IT BACK; without it the
 * section heads, the dark band and the closing line all inherit it and the
 * page ends up four-fifths serif, which is where a draft of this file was.
 *
 * The face is used sparingly on purpose. It is the brand voice, and a brand
 * voice that says every heading is not a voice, it is a typeface. One serif
 * sentence at maximum size reads as the site speaking; the same serif on nine
 * headings reads as the default nobody chose.
 */
.pw h1, .pw h2, .pw h3 {
    font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    /* 500 and zero tracking, set once here so every DM Sans heading on the
       page inherits it. Nothing below restates a weight or a letter-spacing -
       if a heading rule grows one, it has drifted from this line. */
    font-weight: 500;
    letter-spacing: 0;
}

/* ---------- shared micro-type ---------------------------------------- */

/*
 * 1rem IS THE FLOOR for anything a reader reads. Body copy, card
 * descriptions, list items, decks, captions, buttons, tabs and chips are all
 * exactly 1rem (18px, since base.css sets html to 18px). Nothing steps down
 * to 0.88 or 0.83 to make a grid fit - if a card is too tight at 1rem the
 * card is too small, and the fix is the grid, not the type.
 *
 * Below 1rem, and there are only three kinds left, none of them prose:
 *   .pw-eyebrow                            uppercase tracked labels
 *   .pw-meta, .pw-tagpill                  a date, a duration, topic labels
 * Each is a label or a figure that is scanned, not read. Adding a fourth
 * exception means arguing it belongs in that list.
 */

/*
 * NOT a kicker. This label used to sit above five headlines saying "Rescue
 * management software", "The product", "The problem", "Get started" - a line
 * of small caps whose only job was to announce that a heading was coming.
 * They are gone. They said nothing the heading did not, and a page where
 * every section opens with one reads as generated rather than written.
 *
 * What is left are the two places the label carries information the heading
 * cannot: the 01-04 stage numbers in the lifecycle, and the topic family on a
 * blog card, where the dot is a colour key shared with /blog. Both are data.
 * If a new one is not data, it is a kicker - do not add it.
 */
.pw-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.pw-eyebrow::before {
    content: '';
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--st, var(--coral));
    flex: none;
}

/* ---------- masthead -------------------------------------------------- */

.pw-masthead {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
    gap: clamp(2rem, 4vw, 4rem);
    align-items: center;
}

.pw-masthead h1 {
    /* DM Sans, inherited from the .pw h1/h2/h3 rule - no font-family here.
       Bogart is now absent from this page except on the blog lead card, which
       is copied wholesale from /blog and reads as that page's object.

       Tracking is 0, like every heading on the page - see the .pw h1/h2/h3
       rule. It briefly carried -0.03em on the theory that a sans wants
       tightening at display size; it does not here. DM Sans is already
       closely spaced, and negative tracking shuts the counters before it
       shuts the gaps.

       Ceiling is 3.4rem rather than 4.3rem because the headline shares its row
       with the plate: at 4.3rem in a ~640px column "spreadsheets." alone
       overflowed the measure. The column constrains it, so no max-width. */
    font-size: clamp(2.2rem, 1rem + 2.6vw, 3.4rem);
    line-height: 1.06;
    letter-spacing: 0;
    margin: 0;
    text-wrap: balance;
}

.pw-lede {
    margin: 1.15rem 0 0;
    max-width: 56ch;
    color: var(--text-secondary);
    font-size: 1.05rem;
    line-height: 1.55;
}

.pw-actions { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; margin-top: 1.75rem; }
/*
 * SIDE BY SIDE AND EQUAL BELOW 560.
 *
 * Wrapping made each button as wide as its own label, so "Start for free" and
 * "View pricing" sat at different widths with their left edges a few pixels
 * apart - two buttons that read as a rendering fault. A grid makes them one
 * pair: equal columns, one gap, aligned on both edges.
 *
 * auto-fit rather than a flat 1fr 1fr, so the pair drops to one per row only
 * where two genuinely will not fit - below about 360px, where a 9.5rem column
 * would start clipping "Start for free". Nobody has to pick that width; the
 * labels do.
 */
@media (max-width: 560px) {
    .pw-actions {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
        gap: 0.6rem;
    }
    .pw-actions .pw-btn { width: 100%; justify-content: center; padding-inline: 1.1rem; }
}
.pw-fineprint { margin-top: 0.85rem; font-size: 1rem; color: var(--text-muted); }

/* Buttons are 10px, not the site's 20px --radius-md and not a pill. A squarer
   corner is most of what separates "software" from "app store listing", and
   this direction wants the former. */
.pw-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.85rem 1.5rem;
    border-radius: 10px;
    border: 1px solid transparent;
    font-size: 1rem;
    font-weight: 600;
    text-decoration: none;
    line-height: 1;
    transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.pw-btn-primary { background: var(--coral); color: #fff; }
.pw-btn-primary:hover { background: var(--coral-dark); }
.pw-btn-ghost { background: var(--white); border-color: var(--pw-line); color: var(--text-primary); }
.pw-btn-ghost:hover { border-color: var(--text-primary); }
.pw-btn i { font-size: 1.05em; }


/* ---------- images ------------------------------------------------------- */

/*
 * An image, or the grey box standing in for one. Flat grey, rounded, nothing
 * written on it. It replaced a framed browser mock with a hatched ground, a
 * title bar, the filename, the pixel size and a caption - all of which made a
 * design review about the placeholder instead of the layout, and none of which
 * a real screenshot would have kept.
 *
 * Height comes from the child svg's viewBox (see ui_ph), so this box is
 * already exactly the size the real image will be. Dropping in
 * <img class="pw-ph-box" src width height> replaces the svg and moves nothing.
 */
.pw-ph {
    display: block;
    overflow: hidden;
    border-radius: var(--radius-md);
    background: #E7E1DA;
}
/* Lighter on the dark band, where the same grey would disappear into it. */
.pw-ph.is-dark { background: rgba(255, 255, 255, 0.14); }
/* The open-ended card: an outline where the others have a fill. It is a
   different kind of statement - "and anything else you take in" - not another
   item, and that has to read without a caption. */
.pw-cc.is-open .pw-ph { background: transparent; box-shadow: inset 0 0 0 1px rgba(45, 37, 25, 0.2); }

/*
 * A DRAWING IS NOT A SCREENSHOT, and the plate is built for a screenshot: a
 * grey ground the picture will cover completely, with the corners rounded off
 * it. The watercolours are painted on transparent ground and do not cover
 * anything, so that grey stops being a frame and becomes a rectangle sitting
 * behind the artwork - which is exactly what it looked like.
 *
 * AFTER .is-dark on purpose. Both are .pw-ph plus one class, so the later rule
 * wins, and an illustration on the dark band wants no plate either: the ones
 * drawn for dark paper are white ink on nothing.
 *
 * The tour stage does the same thing one level up - see
 * .pw-tour-stage:has(.is-illustration) - because there the chrome is the
 * stage's tint rather than the plate's grey.
 */
.pw-ph.is-illustration {
    background: none;
    border-radius: 0;
}

/* The sizer. No visual content: it exists so the box takes its height from the
   declared asset dimensions through an attribute rather than an inline style. */
.pw-ph-box { display: block; width: 100%; height: auto; }


/* ---------- tour ------------------------------------------------------- */

/* The three grounds a block opens on, named once. ui_section_open() picks the
   class; nothing else should set a section background. .pw-tour and
   .pw-connects predate this and are kept only as the ids they carry. */
.pw-band-section {
    background: var(--pw-band);
    padding: var(--pw-gap) 0;
}

.pw-tour {
    background: var(--pw-band);
    padding: var(--pw-gap) 0;
}
/* .pw-tour-head is gone: the tour opens with ui_head() like every other
   section. Its h2 rule was already identical to .pw-cc-head h2 - the wrapper
   differed only by a max-width that changed nothing on a one-line heading and
   a bottom margin a quarter-rem smaller. Two rules that close together is
   drift waiting to happen, not a distinction. */

/*
 * The tab bar is ONE control, so it is one pill with the tabs inside it, not
 * six loose buttons in a row. The distinction is what makes the selected tab
 * read as a position within a set rather than as a pressed button.
 *
 * It scrolls rather than wraps. A wrapped tab bar on a narrow screen becomes
 * two rows of unequal length and stops looking like a control at all; the
 * jump rail above solved the same problem the same way.
 */
/*
 * THE FRAME EXISTS TO CARRY THE CUT-OFF CUES. The bar itself is the scroller,
 * and anything painted on a scroller travels with its content: a fade meant to
 * mark the right-hand edge would slide away the moment you used it. The frame
 * does not move.
 *
 * The cues are toggled by ui_tour_script() rather than left on, because a bar
 * that fits has nothing beyond either end and a permanent fade over the first
 * and last tab would be a lie told at every width above a phone.
 */
.pw-tabs-frame {
    position: relative;
    display: flex;
    justify-content: center;
    margin: 0 auto clamp(2rem, 3.5vw, 3rem);
    max-width: 100%;
}
.pw-tabs-frame::before,
.pw-tabs-frame::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2.5rem;
    pointer-events: none;
    opacity: 0;
    transition: opacity .18s ease;
    z-index: 1;
}
.pw-tabs-frame::before {
    left: 0;
    border-radius: 999px 0 0 999px;
    background: linear-gradient(to right, var(--white) 30%, rgba(255, 255, 255, 0));
}
.pw-tabs-frame::after {
    right: 0;
    border-radius: 0 999px 999px 0;
    background: linear-gradient(to left, var(--white) 30%, rgba(255, 255, 255, 0));
}
.pw-tabs-frame.has-before::before,
.pw-tabs-frame.has-after::after { opacity: 1; }

.pw-tabs {
    display: flex;
    gap: 0.3rem;
    margin: 0;
    padding: 0.4rem;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
    /* The selected tab is scrolled to this line, not to the very edge, so it
       does not sit flush against the pill's rounded end. */
    scroll-padding-inline: 0.4rem;
    scroll-behavior: smooth;
    background: var(--white);
    border-radius: 999px;
}
.pw-tabs::-webkit-scrollbar { display: none; }
.pw-tab {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.72rem 1.4rem;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: background .18s ease, color .18s ease;
}
.pw-tab i { font-size: 1.05rem; color: var(--text-muted); transition: color .18s ease; }
.pw-tab:hover { color: var(--text-primary); background: var(--cream); }
/* Colour only. Bolding the selected tab reflows the bar - every tab to its
   right shifts a pixel or two on each switch - and it makes the label look
   like a different word rather than the same word selected.
   #F3EBE4 is a literal for now, like the band behind it; both want names in
   tokens.css if this direction ships. */
.pw-tab.is-on { background: #F3EBE4; color: var(--text-primary); }
.pw-tab.is-on i { color: var(--text-primary); }
.pw-tab:focus-visible { outline: 2px solid var(--coral); outline-offset: 2px; }

.pw-tabpanel {
    display: grid;
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
    gap: clamp(1.5rem, 4vw, 3.5rem);
    /* start, not center. The panels differ in height - four points against
       three, two-line titles against one - so centring floated each one to a
       different vertical position and the heading jumped on every tab switch.
       Anchoring the top means only the content below it changes. */
    align-items: start;
}
/*
 * hidden is doing the hiding, and [hidden] needs the display:none restated
 * because the rule above sets display:grid and wins on specificity. Getting
 * this wrong shows all six panels stacked, which is how it looked first.
 *
 * NO-JS: the markup ships panel 0 visible and the rest hidden, so a reader
 * without JS sees a complete first panel and a tab bar that does nothing,
 * rather than an empty section.
 */
.pw-tabpanel[hidden] { display: none; }

.pw-tour-copy h3 {
    /* Tops out at exactly 2rem from ~1125px up, which is every desktop width
       this page is looked at. The clamp only does anything on narrow screens,
       where 2rem beside a stacked screenshot is too much. */
    font-size: clamp(1.5rem, 1rem + 1.6vw, 2rem);
    line-height: 1.2;
    margin: 0;
    text-wrap: balance;
}
.pw-tour-lede {
    margin: 1.1rem 0 0;
    max-width: 46ch;
    font-size: 1rem;
    line-height: 1.6;
    color: var(--text-secondary);
}

/*
 * A summary list, so it is set like one: no disc, no accent colour, no second
 * line of copy per item. The tick is the same drawn artwork the coral badge
 * used, in --text-primary at label size - it marks each line as included
 * rather than decorating it, which is the whole job now that the paragraph
 * above carries the argument.
 */
.pw-points { list-style: none; margin: 1.4rem 0 0; padding: 0; }
.pw-points li {
    position: relative;
    padding: 0 0 0 1.55rem;
    margin-top: 0.62rem;
    font-size: 1rem;
    line-height: 1.4;
    color: var(--text-primary);
}
.pw-points li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.42rem;
    width: 0.78rem;
    height: 0.58rem;
    background: var(--text-primary);
    -webkit-mask: var(--pw-tick) no-repeat center / contain;
            mask: var(--pw-tick) no-repeat center / contain;
}
/* Shared by the tour panels and the blog strip. It lived in the medical split
   block until that section was deleted and went with it; the two remaining
   callers rendered as bare links for exactly one commit. */
.pw-more {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--coral-dark);
    font-size: 1rem;
    font-weight: 600;
    text-decoration: none;
    transition: gap .18s ease;
}
.pw-more:hover { gap: 0.65rem; }
.pw-tour-copy .pw-more { margin-top: 1.7rem; }

/* The tint sits on the STAGE, not the section, so the colour reads as the
   product's backdrop rather than as another band of page. */
.pw-tour-stage {
    padding: clamp(1rem, 2.5vw, 2.25rem);
    border-radius: var(--radius-lg);
    background:
        radial-gradient(120% 120% at 85% 10%, rgba(125, 184, 143, 0.28) 0%, transparent 62%),
        linear-gradient(150deg, var(--sage-light) 0%, #EFF3EC 100%);
}
.pw-tour-stage .pw-ph { box-shadow: var(--shadow-medium); }

.pw-tour-stage:has(.is-illustration) {
    padding: 0;
    border-radius: 0;
    background: none;
}
.pw-tour-stage .pw-ph.is-illustration { box-shadow: none; }

/* ---------- section heads --------------------------------------------- */

/* Top AND bottom. It carried padding-top only, which was invisible while every
   section using it was followed by one that had its own top padding - and
   showed the moment .pw-connects and .pw-features became .pw-section: their
   last row of cards sat flush against the next ground. Matches
   .pw-band-section, so the two are interchangeable. */
.pw-section {
    padding: var(--pw-gap) 0;
}
/* The first section on a page clears the fixed 71px nav. On .pw-section rather
   than on .pw-masthead / .pw-hero because the clearance belongs to being first,
   not to being a hero - a page that opens with a card section needs the same. */
.pw-section.is-first { padding-top: clamp(5.5rem, 9vw, 8rem); }
/* scroll-margin so an anchor jump does not park the heading under the fixed
   nav. The extra 3.6rem that used to be here was clearance for a sticky jump
   rail; the rail is gone. */
.pw-section[id] { scroll-margin-top: calc(var(--pw-nav) + 1.5rem); }

.pw-footnote { margin-top: 1rem; font-size: 1rem; color: var(--text-muted); }

/* ---------- feature grid ------------------------------------------------ */

/* No background of its own - the page is white. This keeps its own padding
   because it is still a full-bleed block, and the cards are held apart from
   the ground by their hairline border alone, which is why .pw-feat-card has
   one rather than relying on a background difference. */
.pw-features {
    padding: var(--pw-gap) 0;
}


/*
 * THE FEATURES MENU, ON THE PAGE. Four groups across, one colour each, in the
 * order includes/nav-features.php declares them - see ui_feature_grid(). The
 * cards this replaced were fifteen identical coral tiles in a 4x4 block, which
 * said nothing about how the modules relate; the grouping is the argument and
 * the colour is what carries it.
 *
 * NOT repeat(4): auto-fit, so a fifth group needs no change here and a narrow
 * window folds to two columns instead of squeezing four. The floor is 16rem
 * rather than the menu's 13 - this is a page section, not a dropdown, and the
 * rows below are set at page scale.
 */
.pw-feat {
    display: grid;
    /*
     * FOUR, NAMED. It was auto-fit on a 16rem minimum, which meant the column
     * count was whatever arithmetic produced at a given width - three columns
     * and an orphaned fourth group anywhere between about 900 and 1290, which
     * is most laptop windows. There are four groups and there is a fixed
     * number of them (a fifth needs a fifth tint declared here and in the two
     * menu files), so the count is the constant and the column width is what
     * gives. Below 900 the whole block becomes the tinted shelves instead.
     */
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2.5rem clamp(1rem, 1.6vw, 1.5rem);
    align-items: start;
}
/* The items are spaced by the column's gap rather than by margins on
   themselves, so the hover ground stays a tight box around each row instead of
   growing to fill the space between them. */
.pw-feat-group {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.pw-feat-heading {
    margin: 0 0 0.25rem;
    padding: 0 1rem;
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.pw-feat-item {
    display: flex;
    align-items: flex-start;
    gap: 0.9rem;
    padding: 1rem;
    border-radius: var(--radius-md);
    /* EVERY BOX THE SAME HEIGHT, and the floor is the WORST CASE rather than
       the common one: two lines of title AND two of description. A one-line
       floor equalised nothing the moment "Intake/Outcome Tracking" wrapped -
       that box grew past it and the column went out of step again, which is
       the bug this was meant to fix.
       Written as its own arithmetic, not a rounded number, so it stays right
       if the type changes: padding, two title lines, the gap, two description
       lines. Nothing in the menu runs to three of either; if something ever
       does, this is a floor and that box grows, which is a visible fault
       rather than clipped text.
       The slack sits under short items, where there is no card edge to make
       it read as empty - these rows only take a ground on hover. */
    min-height: calc(2rem + (2 * 1.1rem * 1.3) + 0.3rem + (2 * 1.5rem));
    text-decoration: none;
    color: var(--text-primary);
    transition: background .2s ease;
}
.pw-feat-item:hover,
.pw-feat-item.is-current { background: var(--pw-band); }

/* One pair per group. --pw-tint names the darker half so the inverted state
   below is one rule for all four, and a fifth group only has to declare its
   colour. */
.pw-feat-icon.coral    { --pw-tint: var(--coral);    background: var(--coral-light); }
.pw-feat-icon.sage     { --pw-tint: var(--sage);     background: var(--sage-light); }
.pw-feat-icon.lavender { --pw-tint: var(--lavender); background: var(--lavender-light); }
/* The blog's medical hue, already a site value - a fourth group needed a
   fourth colour and inventing one would have put a fifth in the palette. */
.pw-feat-icon.rust     { --pw-tint: #B4553F;         background: #F7ECE8; }

/* The same four pairs, named on the GROUP. The tile above needs the dark half
   and the light half; the card below needs both too, so they are declared
   once per group and the tile inherits rather than restating them. */
.pw-feat-group.coral    { --pw-tint: var(--coral);    --pw-wash: var(--coral-light); }
.pw-feat-group.sage     { --pw-tint: var(--sage);     --pw-wash: var(--sage-light); }
.pw-feat-group.lavender { --pw-tint: var(--lavender); --pw-wash: var(--lavender-light); }
.pw-feat-group.rust     { --pw-tint: #B4553F;         --pw-wash: #F7ECE8; }

.pw-feat-icon {
    display: grid;
    place-items: center;
    width: 2.9rem;
    height: 2.9rem;
    flex-shrink: 0;
    border-radius: var(--radius-sm);
    /* Always on, so the tinted square keeps its shape once the row picks up
       the band ground on hover. */
    border: 2px solid var(--white);
    color: var(--pw-tint);
    font-size: 1.45rem;
    transition: background .2s ease, color .2s ease;
}
/* Under the cursor and on the page you are reading: the group's own colour
   becomes the ground, the glyph goes white. */
.pw-feat-item:hover .pw-feat-icon,
.pw-feat-item.is-current .pw-feat-icon {
    background: var(--pw-tint);
    color: var(--white);
}

.pw-feat-text { display: block; min-width: 0; }
.pw-feat-text strong { display: block; font-size: 1.1rem; font-weight: 600; line-height: 1.3; }
.pw-feat-text span   { display: block; margin-top: 0.3rem; color: var(--text-secondary); font-size: 1rem; line-height: 1.5; }

/*
 * BELOW 820 THE CATALOGUE IS FOUR COLOURED SHELVES.
 *
 * Four columns of fifteen items with a line of description each is about
 * 1,400px of list at the foot of every page on the site, and every attempt to
 * shorten it by folding produced a worse thing: chevrons in a ragged grid, a
 * section called "See what else Pawsies can do" that showed nothing until you
 * tapped it, and a script to keep the two states in sync.
 *
 * So nothing folds. The group becomes a card in its own colour, and the items
 * lose the half that does not survive the width: the description, which is a
 * second line under every name and the whole of the length problem. Names and
 * glyphs stay, and a name is what somebody is scanning for. About 600px,
 * everything visible, one tap to any of it, no script.
 *
 * THE COLOUR DOES WHAT THE FOUR COLUMNS DID. On a desktop the grouping is
 * spatial - four headings, four columns, obvious. Stacked, that cue is gone,
 * and the tint this file already assigns one of per group is the only thing
 * left saying which items belong together. That is why these cards are tinted
 * rather than white with a rule around them.
 *
 * THE GLYPH LOSES ITS TILE. A 2.9rem tinted square on a card of the same tint
 * is a square drawn on its own colour. The glyph alone, in the group's ink,
 * says the same thing and leaves the row the height of a line of type instead
 * of the height of a button.
 */
@media (max-width: 900px) {
    .pw-feat {
        /* Two shelves across from 900 down to about 615, one below that: the
           2x2 the four groups want, then the phone. auto-fit finds both from
           the same rule rather than from two more breakpoints. */
        grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
        gap: 0.85rem;
    }
    .pw-feat-group {
        display: grid;
        /* The items find their own column count inside whatever width the card
           got: two across on a phone, one where two cards share a tablet row.
           Nobody has to name those widths - the names do. */
        grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
        gap: 0.1rem 0.9rem;
        padding: 1.05rem 1.15rem 1.15rem;
        border-radius: var(--radius-md);
        background: var(--pw-wash);
    }
    .pw-feat-heading {
        grid-column: 1 / -1;
        margin: 0 0 0.5rem;
        padding: 0;
        /* The group's colour carried at text weight rather than a second grey,
           mixed dark enough to clear 4.5:1 on its own wash. 58% looked right
           in coral and rust and washed out in sage and lavender, which are
           the two light hues - the mix is set for the weakest of the four. */
        color: color-mix(in srgb, var(--pw-tint) 42%, var(--text-primary));
    }
    .pw-feat-item {
        min-height: 44px;
        align-items: center;
        gap: 0.55rem;
        padding: 0.25rem 0;
        border-radius: 10px;
    }
    .pw-feat-item:hover { background: transparent; }
    .pw-feat-icon {
        width: auto;
        height: auto;
        border: 0;
        background: none;
        color: var(--pw-tint);
        font-size: 1.25rem;
    }
    .pw-feat-item:hover .pw-feat-icon,
    .pw-feat-item.is-current .pw-feat-icon { background: none; color: var(--pw-tint); }
    .pw-feat-text strong { font-size: max(0.95rem, 16px); font-weight: 500; }
    .pw-feat-text span { display: none; }
    /* You are here: a white chip on the wash, the one state that has to
       survive losing the hover ground. */
    .pw-feat-item.is-current {
        background: rgba(255, 255, 255, 0.72);
        padding-inline: 0.5rem;
        margin-inline: -0.5rem;
    }
}

/* ---------- connective tissue ------------------------------------------ */

/*
 * Sits on the page white, directly under the tour's #FBF5F0, so the band
 * above it is the thing that reads as coloured rather than this reading as
 * an interruption. No rule between them; the colour change is the edge.
 *
 * .pw-connects rather than .pw-section: it needs its own background across
 * the full width, so the padding lives here and .pw-wrap sits inside it.
 *
 * NO border between the bands. Where two grounds meet, the colour change IS
 * the edge; a hairline on top of it draws a second one and the seam reads as
 * a mistake. Rules are for dividing content that shares a ground - the
 * section heads and the audience rows still use them.
 */
.pw-connects {
    padding: var(--pw-gap) 0;
}

.pw-cc-head { max-width: 46rem; margin: 0 auto clamp(2rem, 4vw, 3rem); text-align: center; }
.pw-cc-head h2 {
    font-size: clamp(1.7rem, 1rem + 1.7vw, 2.6rem);
    line-height: 1.12;
    margin: 0;
    text-wrap: balance;
}
.pw-cc-head p { margin: 1rem auto 0; max-width: 60ch; color: var(--text-secondary); font-size: 1rem; line-height: 1.55; }

/*
 * SIX columns, and each card declares how many it takes. 2+2+2 then 3+3 gives
 * the three-then-two rhythm without a single row wrapper, so the rows are a
 * consequence of the spans rather than a structure that has to be kept in
 * step with them. A card is one entry; changing 2 to 3 re-forms the grid.
 */
.pw-cc-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: clamp(1.25rem, 2.4vw, 2.25rem);
}
/* Span as a class, not a custom property set inline. The grid is six columns
   and only two divisions of it are useful, so an open-ended --span bought
   nothing that these two do not - and a component may not emit a style
   attribute (tools/check-css.php rule 5). */
.pw-cc { grid-column: span 2; }
.pw-cc.is-span2 { grid-column: span 2; }
.pw-cc.is-span3 { grid-column: span 3; }


.pw-cc h3 {
    margin: 1.15rem 0 0;
    font-size: 1.25rem;
    line-height: 1.3;
    text-wrap: balance;
}
.pw-cc p { margin: 0.7rem 0 0; color: var(--text-secondary); font-size: 1rem; line-height: 1.55; }
.pw-cc { display: flex; flex-direction: column; }
.pw-cc-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.8rem;
    color: var(--coral-dark);
    font-size: 1rem;
    font-weight: 600;
    text-decoration: none;
}
.pw-cc-link:hover { gap: 0.65rem; }

/* ---------- audiences --------------------------------------------------- */

/* Same ground as the tour, deliberately. The two are the only band sections
   on the page and giving them one colour makes the white connects grid
   between them read as the interruption rather than as a third variant. */
.pw-audience {
    background: var(--pw-band);
    padding: var(--pw-gap) 0;
}

/* ---------- dark band -------------------------------------------------- */

/* Padding, no margin-top. It used to carry margin-top: clamp(4rem, 8vw,
   6.5rem) on top of the previous section's own bottom padding, which put
   ~11rem of white above the dark ground and made the band read as a floating
   panel rather than as a section. Every other full-bleed block - .pw-tour,
   .pw-band-section - starts flush against what precedes it, and this one now
   does too. Vertical rhythm is padding inside a section, never margin between
   them: margins collapse and this one could not, being on a coloured box. */
.pw-band {
    padding: var(--pw-gap) 0;
    background: var(--text-primary);
    color: var(--cream);
}
/* A child of .pw-wrap now, not the wrap itself: ui_band() goes through
   ui_section_open() like every other block, and that emits the wrap. */
.pw-band-in {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: clamp(2rem, 4vw, 4rem);
    align-items: center;
}
/* No plate. The statement is the whole block, so it centres and takes a
   measure of its own rather than keeping the left column of a two-column grid
   and leaving the right half empty. The <p> needs its margin restated because
   .pw-band p caps it at 48ch, which off-centres a centred paragraph. */
.pw-band-in.is-solo {
    grid-template-columns: minmax(0, 1fr);
    max-width: 48rem;
    margin-inline: auto;
    text-align: center;
}
.pw-band-in.is-solo p { margin-inline: auto; }
/* Scoped to .pw-band, which is the class ui_section_open() gives ANY block
   asked for the dark ground - so a card section or a hero on 'dark' inherits
   the same ink without restating it. */
.pw-band h2 {
    font-size: clamp(1.7rem, 1rem + 1.7vw, 2.6rem);
    line-height: 1.12;
    margin: 0;
    text-wrap: balance;
}
.pw-band p { margin: 1.1rem 0 0; max-width: 48ch; color: rgba(255, 251, 247, 0.72); font-size: 1rem; line-height: 1.6; }

/* ---------- writing strip --------------------------------------------- */

/* Centred head, matching the tour, the connective grid, the audiences and the
   feature index. This was the last section using ht_head() - the left-aligned
   title with a hairline rule running off to a right-hand count - which by then
   was the odd one out rather than the house style. ht_head() had no callers
   left after this and went with it, along with .pw-head, .pw-rule, .pw-note
   and .pw-deck.

   No closing "Read the blog" link either: all four cards already go there, and
   the nav carries Blog on every page. */

/*
 * The blog listing's own card, narrowed. The family colours are declared on
 * .pw for the lifecycle already; these are the same five, so the dot on a
 * post here is the same colour as the dot on that post in /blog.
 */
.pw-writing {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    gap: clamp(1rem, 1.8vw, 1.5rem);
}

/*
 * The lead, matching .bl-lead in blog.php value for value.
 *
 * The radial wash is --coral-light and is AGNOSTIC of the post's topic family
 * - deliberately, and this is the one place the family colour does not drive
 * the paint. A wash tinted per topic made the card a different colour every
 * time the newest post changed subject, so the section had no fixed identity;
 * the family is already stated by the dot in the eyebrow and by the tag pills,
 * which is where a colour code belongs. --st is still set on the card because
 * those two read it.
 */
.pw-lead {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 21rem;
    padding: clamp(1.6rem, 2.8vw, 2.5rem);
    border-radius: var(--radius-lg);
    border: 1px solid var(--pw-line);
    background:
        radial-gradient(120% 100% at 8% 0%, var(--coral-light) 0%, transparent 62%),
        linear-gradient(158deg, var(--white) 0%, var(--cream-dark) 100%);
    text-decoration: none;
    color: inherit;
    transition: transform .25s cubic-bezier(.16,1,.3,1), box-shadow .25s ease;
}
.pw-lead:hover { transform: translateY(-3px); box-shadow: var(--shadow-medium); }
.pw-lead h3 {
    /* Bogart, and the only other one on the page after the masthead h1. It is
       what makes this read as the blog's lead card rather than as a card that
       links to it. If it is one serif too many, this is the one to drop. */
    font-family: 'bogart', Georgia, serif;
    font-weight: 500;
    font-size: clamp(1.5rem, 1rem + 1.5vw, 2.3rem);
    line-height: 1.12;
    letter-spacing: -0.022em;
    margin: 0.9rem 0 0;
    text-wrap: balance;
}
.pw-lead p {
    margin: 0.9rem 0 0;
    max-width: 60ch;
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1.55;
}

/* Meta and tag pills sit below the 1rem floor, like .pw-eyebrow: a date, a
   duration and three topic labels are scanned, not read. Values match
   blog.php so the two cards are the same object. */
.pw-meta {
    margin-top: 1.1rem;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.9rem;
    font-size: 0.82rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.pw-tagpill {
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--st) 12%, transparent);
    color: color-mix(in srgb, var(--st) 78%, var(--text-primary));
    font-size: 0.74rem;
    font-weight: 500;
}

.pw-stack { display: grid; grid-template-rows: repeat(2, 1fr); gap: clamp(1rem, 1.8vw, 1.5rem); }
.pw-post {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 1.3rem 1.4rem;
    background: var(--white);
    border: 1px solid var(--pw-line);
    border-radius: var(--radius-md);
    text-decoration: none;
    color: inherit;
    transition: transform .22s cubic-bezier(.16,1,.3,1), box-shadow .22s ease, border-color .22s ease;
}
.pw-post:hover { transform: translateY(-2px); box-shadow: var(--shadow-soft); border-color: transparent; }
/* No byline on these two. Date and reading time under every headline is rows
   of figures nobody came for; the lead carries them because it has the room
   and because they are part of the object being copied from /blog. */
.pw-post h3 {
    margin: 0.5rem 0 0;
    font-size: 1.1rem;
    line-height: 1.33;
    text-wrap: balance;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pw-post p {
    margin: 0.5rem 0 0;
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1.5;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.pw-lead:hover h3, .pw-post:hover h3 { color: var(--coral-dark); }

/* ---------- closing CTA ------------------------------------------------ */

.pw-cta {
    padding: var(--pw-gap) 0;
    border-top: 1px solid var(--pw-line);
    text-align: center;
}
.pw-cta h2 { font-size: clamp(1.8rem, 1.1rem + 1.8vw, 2.7rem); line-height: 1.12; margin: 0; }
.pw-cta .pw-actions { justify-content: center; }

/* ---------- related resources ------------------------------------------ */

.pw-related h2 {
    margin: 0 0 1rem;
    color: var(--text-muted);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}
.pw-related ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.65rem 2rem;
    margin: 0;
    padding: 0;
    list-style: none;
}
.pw-related a {
    color: var(--coral-dark);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.5;
    text-decoration: none;
}
.pw-related a:hover { text-decoration: underline; }

/* ---------- notes ------------------------------------------------------- */

/*
 * The brief's `trio`. Three headed paragraphs across one ground - see
 * ui_notes_section() for why this is not the card grid with the pictures
 * taken out.
 *
 * NO CARD. No border, no fill, no radius: the ground is the container and the
 * columns are held apart by the gap. A card here would read as a card missing
 * its image, which is the exact impression the block exists to avoid.
 *
 * auto-fit, so four notes wrap rather than squeeze and the block is not
 * secretly a three-column layout with a three-item name.
 */
.pw-notes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: clamp(1.75rem, 3vw, 3rem);
}
.pw-note h3 {
    margin: 0;
    font-size: 1.25rem;
    line-height: 1.3;
    text-wrap: balance;
}
.pw-note p { margin: 0.7rem 0 0; color: var(--text-secondary); font-size: 1rem; line-height: 1.6; }
/* The dark ground gets the band's own ink, matching .pw-band p. Without this
   the secondary grey survives onto near-black and the paragraph disappears. */
.pw-band .pw-note p { color: rgba(255, 251, 247, 0.72); }

/* ---------- faq --------------------------------------------------------- */

/*
 * Native <details>, so everything below is presentation only - no state class
 * and no script. [open] is the browser's, which is why the chevron rotation
 * keys off it.
 */
.pw-faq { max-width: 46rem; margin: 0 auto; }
.pw-faq-item { border-bottom: 1px solid var(--pw-line); }
.pw-faq-item summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 1.25rem 0;
    /* 1.05rem, not the 1rem body size: a question is the thing being scanned
       and the answer under it is the thing being read. */
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--text-primary);
    cursor: pointer;
    /* The default disclosure triangle, removed in both dialects - the chevron
       on the right replaces it. -webkit- is not legacy here: Safari still
       needs it and ignores the standard property. */
    list-style: none;
}
.pw-faq-item summary::-webkit-details-marker { display: none; }
.pw-faq-item summary:hover { color: var(--coral-dark); }
/* On the <summary>, not the item: the focus ring has to sit on the thing that
   actually takes the keyboard, and an outline around the whole open answer
   says the paragraph is focused. */
.pw-faq-item summary:focus-visible { outline: 2px solid var(--coral); outline-offset: 3px; }
.pw-faq-item summary i {
    flex-shrink: 0;
    font-size: 1.1rem;
    color: var(--text-muted);
    transition: transform .25s ease;
}
.pw-faq-item[open] summary i { transform: rotate(180deg); }
.pw-faq-a { padding: 0 0 1.35rem; }
.pw-faq-a p { margin: 0; color: var(--text-secondary); font-size: 1rem; line-height: 1.7; }
.pw-faq-a .pw-more { margin-top: 0.9rem; }

/* ---------- responsive -------------------------------------------------- */

/*
 * WIDE SCREENS GET AIR, and the masthead gets the most of it.
 *
 * clamp(5.5rem, 9vw, 8rem) tops out at 144px, which is right at 1000px and
 * mean at 1600: the opening block sat as close to the nav on a 27-inch
 * monitor as it did on a laptop, and the one thing a big screen is for is
 * room. The gap between the two columns opens with it, so the copy and the
 * drawing stop reading as one dense band.
 *
 * FIRST SECTION ONLY. Every other section keeps --pw-gap: a page that breathes
 * evenly all the way down has no opening, and the point of the extra space
 * here is that this block is the first thing on the page.
 */
@media (min-width: 1200px) {
    .pw-section.is-first { padding-top: 9.5rem; }
    .pw-masthead {
        gap: clamp(4rem, 5.5vw, 7rem);
        padding-bottom: 2.5rem;
    }
    /* The lede stops short of the column edge rather than running its full
       width: 58 characters is a comfortable measure, and the shortfall is
       what makes the column look composed rather than filled. */
    .pw-masthead .pw-lede { max-width: 34rem; }
}

/*
 * FOUR COLUMNS OR TWO, NEVER THREE. There are four groups, so a three-column
 * grid puts three on the first row and one alone on the second, which reads as
 * a mistake rather than a layout. Between 1200 and 900 the four columns hold
 * and the items compact instead: a smaller tile, tighter gaps, and names that
 * wrap to more lines. The grid gets taller; it does not get ragged.
 */
@media (max-width: 1200px) and (min-width: 901px) {
    /* The count is set on .pw-feat itself; this band only tightens what is
       inside the four columns as they narrow. */
    .pw-feat { gap: 2rem clamp(0.5rem, 1.2vw, 1rem); }
    .pw-feat-item { padding: 0.75rem; gap: 0.7rem; }
    .pw-feat-icon { width: 2.4rem; height: 2.4rem; font-size: 1.25rem; }
    .pw-feat-text strong { font-size: 1.05rem; }
    .pw-feat-heading { padding-inline: 0.75rem; }
}

@media (max-width: 1200px) {
    /* 6 -> 2 columns: every card spans the full row, which is the only honest
       reduction. Halving the spans instead leaves a 1-wide card that is too
       narrow for its own panel. */
    .pw-cc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .pw-cc, .pw-cc.is-span2, .pw-cc.is-span3 { grid-column: span 1; }
    .pw-writing { grid-template-columns: 1fr; }
    .pw-stack { grid-template-rows: none; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1000px) {
    .pw-masthead { grid-template-columns: 1fr; }
    /*
     * THE PICTURE GOES FIRST, and only here. Everywhere else on the site the
     * image follows its copy, because everywhere else the image is a
     * screenshot and a screenshot with no heading above it means nothing. The
     * masthead's plate is not that: it is the drawing that says what kind of
     * thing this is, and stacked underneath five lines of body copy it is
     * below the fold on every phone. The first screen is either the drawing
     * and the headline, or it is a wall of text.
     */
    .pw-masthead > .pw-ph { order: -1; }
    .pw-tabpanel { grid-template-columns: 1fr; }
    .pw-tour-stage { order: 2; }
    .pw-band-in { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    /* .pw-feat is NOT here any more: below 900 the catalogue is the shelf
       block in the feature-grid section, and its auto-fit already drops to one
       column at about 615px. Two rules setting the same grid from two places
       is how one of them silently wins. */
    .pw-cc-grid { grid-template-columns: 1fr; }
    .pw-stack { grid-template-columns: 1fr; }
    .pw-related ul { flex-direction: column; }
    /*
     * .pw-masthead { padding-top: 6rem } WAS HERE and it was clearance for the
     * fixed nav - which .pw-section.is-first above is already providing. Two
     * clearances for one nav put 184px of white between a 67px bar and the
     * headline on a phone, most of a first screen spent on nothing. The
     * section keeps the job; being a masthead is not what earns the padding.
     */
}
/*
 * TOUCH, which is not the same question as WIDTH and gets its own query.
 *
 * A 29px-tall link is comfortable under a cursor and a miss under a thumb, and
 * it is a miss on a 1024px tablet exactly as much as on a 390px phone - so the
 * rules that widen a hit area key off the pointer, and only the rules that are
 * really about space key off the viewport. 44px is the floor Apple and Google
 * both publish; these two links were sitting at 29 with no padding at all,
 * because the card around them gave them none and a cursor did not care.
 *
 * NOTHING HERE SHRINKS ANYTHING. Every rule in this block adds hit area or
 * type size, so a browser that does not match the query loses nothing and the
 * desktop design is untouched by it.
 */
@media (pointer: coarse) {
    .pw-cc-link,
    .pw-more {
        min-height: 44px;
        align-items: center;
    }
    /* The tabs are 40px with the padding that suits a cursor. They are also
       the one control on the home page that a reader has to hit repeatedly. */
    .pw-tab { min-height: 44px; }
    /* The FAQ summary is already 98px and the buttons 51px. Left alone on
       purpose: padding added to something that already clears the floor is
       padding that shows. */
}

/*
 * SMALL SCREENS, where the argument is space rather than fingers.
 *
 * The section gap is the one that matters. --pw-gap is the vertical padding
 * every block gets, top and bottom, so 3.5rem is 126px of air between one
 * section and the next; on a 390px phone that is a third of the screen spent
 * on the join, and the home page ran to 12,000px partly because of it. 2.9rem
 * still reads as a section break and gives about a screenful back over the
 * length of a page.
 *
 * The label sizes are the site's own floor being applied where the desktop
 * design had drifted under it. 0.72rem is 13px, which is a caption on a
 * 27-inch monitor and a squint on a phone.
 */
/* The labels first, and up to 820 rather than 560: a 13px eyebrow is no more
   readable on a tablet held at arm's length than on a phone, and 820 is where
   the site already stops being a desktop (it is the breakpoint the feature
   grid collapses on). */
/*
 * max(), not a flat rem. The root font size is fluid now (see base.css), so
 * 0.85rem is 15.3px on a monitor and 13.6px on a phone - which is the wrong
 * way round for exactly these labels. The px half is a floor on the smallest
 * screens; the rem half keeps them in proportion everywhere else. A floor
 * against a squint is a physical measurement, not a typographic one.
 */
@media (max-width: 820px) {
    .pw-eyebrow { font-size: max(0.85rem, 15px); }
    .pw-tagpill { font-size: max(0.85rem, 15px); }
    .pw-related h2 { font-size: max(0.85rem, 15px); }
    .pw-meta { font-size: max(0.85rem, 15px); }
}

/* The section gap is a phone question rather than a tablet one: at 768 there
   is room for the air, and taking it away would only make the page look
   cramped on the width that reads most like the desktop design. */
@media (max-width: 560px) {
    body { --pw-gap: 2.9rem; }
}

@media (prefers-reduced-motion: reduce) {
    .pw-btn, .pw-feat-card, .pw-more, .pw-more i, .pw-post, .pw-lead, .pw-tab, .pw-tab i, .pw-cc-link { transition: none; }
    /* The chevron still points the right way - only the sweep to it goes. */
    .pw-faq-item summary i { transition: none; }
    .pw-lead:hover { transform: none; }
    .pw-feat-card:hover { transform: none; }
    .pw-cc-link:hover { gap: 0.4rem; }
    .pw-more:hover { gap: 0.4rem; }
    .pw-post:hover { transform: none; }
}
/* =====================================================================
   Blocks that started on the feature page.

   Everything below was .ft- while it lived in a feature-page-only file. The
   prefix went when the rules became blocks: a hero, a chip row and a split row
   are sections any page can open with, and a second prefix said they were not.
   ===================================================================== */

/* ---------- hero -------------------------------------------------------- */

/*
 * Narrower and centred, unlike the home masthead. A feature page is reached
 * by someone who already knows what the product is and wants one answer; the
 * home page has to introduce itself, which is why it earns a two-column
 * opening with a screenshot in it and this does not.
 */
.pw-hero {
    max-width: 46rem;
    margin: 0 auto;
    text-align: center;
}
.pw-hero h1 {
    font-size: clamp(2.2rem, 1rem + 2.6vw, 3.4rem);
    line-height: 1.06;
    letter-spacing: 0;
    margin: 0;
    text-wrap: balance;
}
/* hero.title carries a <span> around its second line and the OLD stylesheet
   coloured it coral. Deliberately not carried over: coral is the action
   colour on these pages - buttons, links, the tick discs - and a headline
   that is not a link should not wear it. The span still marks the line break
   the copy was written with. */

.pw-hero p {
    margin: 1.15rem auto 0;
    max-width: 52ch;
    color: var(--text-secondary);
    font-size: 1.05rem;
    line-height: 1.55;
}
.pw-hero .pw-actions { justify-content: center; }

/* ---------- species grid ------------------------------------------------ */


/* ---------- field type chips -------------------------------------------- */

.pw-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.55rem;
    max-width: 52rem;
    margin: 0 auto;
}
.pw-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 1.1rem;
    border-radius: 999px;
    border: 1px solid var(--pw-line);
    background: var(--white);
    color: var(--text-primary);
    font-size: 1rem;
}
.pw-chip i { color: var(--coral); font-size: 1.15rem; }

/* ---------- alternating rows -------------------------------------------- */

.pw-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: clamp(2rem, 4vw, 4rem);
    align-items: center;
}
/* Rows need space between them; the section's own padding only covers the
   ends. Grid on the wrap rather than margins on the rows so the last row does
   not need a special case. */
.pw-rows .pw-wrap { display: grid; gap: clamp(3rem, 6vw, 5rem); }

/*
 * nth-child on the ROW's position, not a flag on the data: which side the
 * image sits is a property of where the row falls in the sequence, and a
 * hand-written 'reverse' is how a list ends up with two images on the same
 * side after someone inserts one in the middle.
 *
 * DESCENDANT, not child. It was `.pw-rows > .pw-row` and silently stopped
 * matching when ui_split_rows() moved onto ui_section_open(), which emits a
 * .pw-wrap between the section and the rows. Nothing errored - the rows just
 * all rendered the same way round. A combinator that depends on a wrapper the
 * component controls is a combinator that breaks when the component changes.
 */
.pw-rows .pw-row:nth-child(even) .pw-row-copy { order: 2; }

.pw-row h2 {
    font-size: clamp(1.6rem, 1rem + 1.5vw, 2.2rem);
    line-height: 1.16;
    margin: 0;
    text-wrap: balance;
}
/* Matches .pw-tour-copy .pw-more - the tick list ends the copy column and the
   link needs to clear it by more than the list's own spacing, or it reads as a
   fifth bullet. */
.pw-row-copy .pw-more { margin-top: 1.6rem; }
.pw-row > .pw-row-copy > p {
    margin: 1rem 0 0;
    max-width: 50ch;
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1.6;
}

/* ---------- responsive -------------------------------------------------- */

@media (max-width: 1000px) {
    .pw-row { grid-template-columns: 1fr; }
    /*
     * THE PICTURE LEADS, in every row, once they stack.
     *
     * The alternation is a desktop idea and it dies here: in one column it is
     * not a rhythm, it is two rows that happen to be ordered differently.
     * Which leaves the question of what comes first, and on a phone that is
     * the picture - the same answer the masthead gives. A row is one screen
     * of scrolling; the picture is what tells you the row has changed, and
     * under the copy it arrives after the reader has already decided.
     *
     * :not(.pw-row-copy) rather than naming the plate, so a row carrying a
     * drawing, a screenshot or the grey box that stands in for one all put the
     * same thing first.
     */
    .pw-rows .pw-row:nth-child(even) .pw-row-copy { order: 0; }
    .pw-row > :not(.pw-row-copy) { order: -1; }
}

/* ---------- nav width ---------------------------------------------------- */

/*
 * includes/nav.php is a shared component at 1184px and these pages run at
 * 1440px, so without this the logo sits inboard of the headline beneath it.
 *
 * BOTH rules are needed and only one of them used to be here. .nav carries
 * `padding: 0.75rem 2rem` of its own, a flat 2rem that does not track
 * --pw-pad; .nav-inner then centres inside what is left. At widths where
 * --pw-pad resolves below 2rem the nav ended up further inset than the
 * content, which is the misalignment. Zeroing the outer gutter and putting
 * the page's own padding on the inner element makes the logo land on the same
 * line as everything under it at every width.
 *
 * blog.php carries a version of this for the same reason; all three want
 * reconciling in nav.php itself one day, which is why that file is in $LEGACY.
 */
body .nav { padding-inline: 0; }
body .nav-inner { max-width: var(--pw-max); padding-inline: var(--pw-pad); }
/* The features band is full-bleed, so the cap and gutter that align it live on
   its grid rather than on the panel. Same two values as .nav-inner above and
   for the same reason: the first item in the menu should start on the same
   line as the logo above it and the headline below it. */
body .nav-mega-grid { max-width: var(--pw-max); padding-inline: var(--pw-pad); }
