/* Yard Layout - mobile first, widening to a two column planner on larger screens. */

:root {
    /*
     * What the browser paints for itself: scrollbars, the space behind the page, the
     * spinners on a number field, the popup a <select> opens.
     *
     * It has to be declared here, against the same three states as the palette, and not
     * as a <meta> tag. The meta only knows the operating system's preference, so a reader
     * whose system is dark and who then pressed the light button on this page got a light
     * page with black scrollbars down the side of it.
     */
    color-scheme: light;
    --bg: #faf8f4;
    --surface: #ffffff;
    --ink: #22201c;
    --muted: #6f6a60;
    --line: #e3ded3;
    /* The logo's own green, taken darker. The artwork's #5A8B3E cannot carry this job --
       against the page it reaches 3.81:1 and under white label text 4.04:1, both short of
       the 4.5:1 that body-sized text needs -- but the mismatch that showed once the logo
       went in was hue rather than depth: the artwork sits at hue 98 and the old accent at
       124, which is a different green rather than a deeper one. This is the artwork's hue
       and saturation held, its lightness dropped to 30%, and it clears the bar at 5.90:1
       on the page and 6.26:1 under white. */
    --accent: #456A2F;
    --accent-soft: rgba(69, 106, 47, 0.12);
    /* Text sitting on the accent, rather than #fff written out at each of its uses:
       the dark palette keeps the accent light enough that its label has to go dark. */
    --on-accent: #ffffff;
    /* Destructive. */
    --danger: #a33a2a;
    --danger-soft: rgba(163, 58, 42, 0.08);
    /* Hairline around a colour swatch, so a pale material still reads as a tile. */
    --swatch-line: rgba(34, 32, 28, 0.14);
    /*
     * The sketch is paper, in both themes.
     *
     * The canvas paints this colour itself (PAPER in planner.ts) and the box around it
     * matches, so the sheet reads as one surface. It does not darken with the rest of the
     * page: a plan is a drawing on paper, the material colours are mixed against a light
     * ground, and inverting it would make every swatch a lie about what gets built.
     */
    --paper: #f6f4f0;
    /*
     * The rest of the paper's palette, and the reason it is a separate set.
     *
     * The zoom buttons, the wall menu, the hint line and the save warning are positioned
     * over the sketch, not over the page. They inherited --ink and --muted, which in dark
     * meant pale grey text on a near-white sheet -- the zoom controls were invisible. So
     * anything that sits on the paper takes its colours from here, and these are declared
     * once and never redefined by either dark block: the sheet does not change theme, so
     * neither does anything resting on it.
     */
    --paper-ink: #22201c;
    --paper-muted: #6f6a60;
    --paper-line: #e3ded3;
    --paper-surface: #ffffff;
    /* The strip that says a save was refused. It sits on the paper, so it stays light. */
    --warn-line: #d9a441;
    --warn-bg: #fdf6e6;
    --warn-ink: #6b4c12;
    --radius: 10px;
    --shadow: 0 1px 2px rgba(34, 32, 28, 0.06), 0 8px 24px rgba(34, 32, 28, 0.05);
    --shadow-pop: 0 12px 28px rgba(34, 32, 28, 0.18);
    --shadow-float: 0 6px 20px rgba(34, 32, 28, 0.18);
    --shadow-chip: 0 1px 3px rgba(34, 32, 28, 0.18);
}

/*
 * Dark. Only the tokens move; every rule below is written once, against them.
 *
 * Three blocks rather than one, because the theme has three states. An explicit choice
 * stamps data-theme on the root and must win in both directions, and the default -- no
 * attribute at all -- follows the operating system. The media query is therefore guarded
 * against a root that has explicitly asked for light.
 */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
        --bg: #17181a;
        --surface: #202225;
        --ink: #e8e6e1;
        --muted: #a19c93;
        --line: #34363a;
        /* The page went dark, so the accent goes the other way: the artwork's hue and
           saturation held, lightness lifted until it clears 4.5:1 on the dark ground
           instead of on the light one. Its label flips dark to match. */
        --accent: #8FBF6A;
        --accent-soft: rgba(143, 191, 106, 0.16);
        --on-accent: #14210b;
        --danger: #e08573;
        --danger-soft: rgba(224, 133, 115, 0.14);
        --swatch-line: rgba(255, 255, 255, 0.22);
        --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
        --shadow-pop: 0 12px 28px rgba(0, 0, 0, 0.55);
        --shadow-float: 0 6px 20px rgba(0, 0, 0, 0.5);
        --shadow-chip: 0 1px 3px rgba(0, 0, 0, 0.45);
    }
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --bg: #17181a;
    --surface: #202225;
    --ink: #e8e6e1;
    --muted: #a19c93;
    --line: #34363a;
    --accent: #8FBF6A;
    --accent-soft: rgba(143, 191, 106, 0.16);
    --on-accent: #14210b;
    --danger: #e08573;
    --danger-soft: rgba(224, 133, 115, 0.14);
    --swatch-line: rgba(255, 255, 255, 0.22);
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
    --shadow-pop: 0 12px 28px rgba(0, 0, 0, 0.55);
    --shadow-float: 0 6px 20px rgba(0, 0, 0, 0.5);
    --shadow-chip: 0 1px 3px rgba(0, 0, 0, 0.45);
}

* {
    box-sizing: border-box;
}

/* A class rule with display beats the hidden attribute, which left the wall menu
   and the corner buttons permanently on screen, swallowing clicks. */
[hidden] {
    display: none !important;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    font-size: 16px;
    line-height: 1.55;
}

h1, h2, h3 {
    line-height: 1.2;
    margin: 0 0 0.5em;
}

h1 {
    font-size: clamp(1.6rem, 4.5vw, 2.4rem);
    letter-spacing: -0.02em;
}

a {
    color: var(--accent);
}

/*
 * Placeholder text.
 *
 * Set explicitly because the browsers do not theme it: Chrome paints every placeholder a
 * fixed #757575 whatever the page is, which is 3.5:1 on the dark surface -- under the 4.5:1
 * that text needs, and visibly murky. Firefox instead takes the input's own colour at 54%
 * opacity, which lands somewhere else again, so the opacity is pinned as well and both end
 * up at the one colour this palette already uses for quieter text.
 */
::placeholder {
    color: var(--muted);
    opacity: 1;
}

.wrap {
    width: 100%;
    max-width: 1440px;
    margin-inline: auto;
    padding-inline: max(16px, env(safe-area-inset-left)) max(16px, env(safe-area-inset-right));
}

.skip-link {
    position: absolute;
    left: -9999px;
}

.skip-link:focus {
    left: 8px;
    top: 8px;
    z-index: 10;
    background: var(--surface);
    padding: 8px 12px;
    border-radius: var(--radius);
}

/* The name set as the wordmark rather than in the page's own type.
 *
 * The words are still there: full size, ordinary inline flow, simply painted in nothing,
 * with the artwork laid over the top of them. That matters more than it looks. Every other
 * way of taking words off the screen splits the sentence around them:
 *
 *   clipped and positioned out of flow   -> rendered text and screen readers get "y ard"
 *   moved into the image's alt text      -> rendered text loses the words altogether
 *   an inline-block squeezed to no width -> screen readers get "y ard"
 *
 * Anything out of the normal flow ends the run of text on either side of it and a space
 * goes in, which costs the name in the h1 and in the questions further down -- both of them
 * the page saying what it is. Left in flow and simply not painted, the name stays whole to
 * a crawler, to a screen reader, to find-on-page and to the clipboard.
 *
 * The artwork is laid over the words rather than set between them, so its width is the
 * width of what it replaces and it cannot drift out of step with the sentence, whatever
 * the reader's font measures. Everything else follows from the artwork's own proportions:
 * it is 4.2476 as wide as it is tall, and its baseline sits 0.1922 of its height up from
 * the bottom, which is what the offset below lines up with the baseline of the line it
 * is sitting on. */
.brandmark {
    position: relative;
    white-space: nowrap;
}

.brandmark__text {
    color: transparent;
}

.brandmark__art {
    position: absolute;
    left: 0;
    bottom: 0.02em;
    width: 100%;
    height: auto;
    max-width: none;
}

/* ---- chrome ---------------------------------------------------------- */

.site-header {
    background: var(--surface);
    border-bottom: 1px solid var(--line);
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 60px;
    flex-wrap: wrap;
}

.brand {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}

/* One image, so only the height is set: the width follows the artwork instead of being
   asserted a second time here and stretching it if the artwork is ever redrawn. */
.brand__logo {
    display: block;
    height: 30px;
    width: auto;
}

/*
 * Which of the two wordmarks is showing.
 *
 * The artwork is drawn in the brand green and a near-black, and the near-black half of the
 * name disappears on a dark page. <picture> cannot do this job: its media queries see the
 * operating system's preference and know nothing about a theme chosen with the button here.
 * So both are in the markup and this decides, in the same three blocks the palette uses.
 */
.brandmark__art--dark,
.brand__logo--dark {
    display: none;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .brandmark__art--light,
    :root:not([data-theme="light"]) .brand__logo--light {
        display: none;
    }

    :root:not([data-theme="light"]) .brandmark__art--dark,
    :root:not([data-theme="light"]) .brand__logo--dark {
        display: block;
    }
}

:root[data-theme="dark"] .brandmark__art--light,
:root[data-theme="dark"] .brand__logo--light {
    display: none;
}

:root[data-theme="dark"] .brandmark__art--dark,
:root[data-theme="dark"] .brand__logo--dark {
    display: block;
}

/* Forced colours repaints the words in the system's own text colour, and "transparent" is
   not a colour it keeps -- so they would come back underneath the artwork. The artwork
   stands down instead and the name is set as ordinary text, which is the whole point of
   having left the words in place.

   Last, and matching the theme swap above selector for selector, because that swap turns
   the artwork back on: a rule of equal weight only wins by coming after it. */
@media (forced-colors: active) {
    .brandmark__art,
    :root:not([data-theme="light"]) .brandmark__art,
    :root[data-theme="dark"] .brandmark__art {
        display: none;
    }
}

.site-nav {
    display: flex;
    gap: 4px;
}

.site-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 12px;
    border-radius: var(--radius);
    text-decoration: none;
    color: var(--muted);
    font-weight: 550;
}

.site-nav a:hover {
    background: var(--accent-soft);
    color: var(--accent);
}

/* Sits in the nav row as a third item, sized like the two links beside it. Only one of
   the two glyphs is ever shown: the one for the theme the button would switch to. */
.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    border: none;
    border-radius: var(--radius);
    background: none;
    color: var(--muted);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
}

.theme-toggle:hover {
    background: var(--accent-soft);
    color: var(--accent);
}

/* aria-pressed carries which theme is on, so the glyphs follow it rather than needing a
   second class kept in step with it. Pressed means dark, and dark offers the sun. */
.theme-toggle__sun {
    display: none;
}

.theme-toggle[aria-pressed="true"] .theme-toggle__sun {
    display: inline;
}

.theme-toggle[aria-pressed="true"] .theme-toggle__moon {
    display: none;
}

.site-footer {
    margin-top: 48px;
    padding: 24px 0 calc(40px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--line);
    color: var(--muted);
    font-size: 0.85rem;
}

.site-footer p {
    margin: 0 0 4px;
}

/* ---- intro ----------------------------------------------------------- */

/* The heading and the line under it are centred over the planner. The measure stays at
   720px, because a line of body text as wide as the sketch is a line nobody finishes --
   but a left-aligned block that narrow, above something nearly twice as wide, reads as
   having drifted off to one side rather than as sitting at the top of the page. */
.intro {
    padding-top: 28px;
    padding-bottom: 8px;
    max-width: 720px;
    margin-inline: auto;
    text-align: center;
}

/* The column is centred; the words inside it are not. A centred heading is a heading, but
   five lines of centred body text are ragged down both edges and every line starts in a
   different place, which is why the eye keeps losing them. */
.intro-lede {
    max-width: 720px;
    margin-block: 0;
    margin-inline: auto;
    color: var(--muted);
}

/* ---- planner shell --------------------------------------------------- */

.planner {
    display: grid;
    gap: 16px;
    padding-top: 20px;
    grid-template-areas:
        "stage"
        "tools"
        "totals";
}

.planner__stage {
    grid-area: stage;
    min-width: 0;
}

.planner__tools {
    grid-area: tools;
}

.planner__totals {
    grid-area: totals;
}

.panel {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 14px;
    box-shadow: var(--shadow);
}

.panel__title {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    margin-bottom: 12px;
}

.panel__hint {
    margin: 12px 0 0;
    font-size: 0.8rem;
    color: var(--muted);
}

/* ---- action menu ------------------------------------------------------ */

/* A row of joined buttons reads as a mode switch -- Replace / Add layer sits right below
   it doing exactly that -- so three destructive actions in that shape looked like a
   choice of state rather than three things that happen the moment you touch them. One
   button opening a menu instead, where each item can say in a line what it takes away
   and what it leaves. */
.menu-anchor {
    position: relative;
    display: inline-flex;
}

.action-menu {
    position: fixed;
    z-index: 40;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 6px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-pop);
}

.action-menu__item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 12px;
    border: none;
    border-radius: 7px;
    background: none;
    font: inherit;
    text-align: left;
    color: var(--ink);
    cursor: pointer;
}

.action-menu__item:hover {
    background: var(--accent-soft);
}

.action-menu__name {
    font-weight: 600;
    font-size: 0.92rem;
}

/* The part that answers "and what happens to the rest of my plan?" at the moment of
   the decision, rather than in a tooltip a phone never shows. */
.action-menu__note {
    font-size: 0.76rem;
    line-height: 1.35;
    color: var(--muted);
}

/* The only one that also forgets the saved plan, so it is marked as the different kind
   of thing it is. */
.action-menu__item--danger {
    margin-top: 4px;
    border-top: 1px solid var(--line);
    border-radius: 0 0 7px 7px;
    padding-top: 12px;
}

.action-menu__item--danger .action-menu__name {
    color: var(--danger);
}

.action-menu__item--danger:hover {
    background: var(--danger-soft);
}

/* A saved plan and the button that deletes it, on one line. The name takes the room and
   the × takes what is left, so a long name never pushes the delete off the edge. */
.action-menu__row {
    display: flex;
    align-items: stretch;
    gap: 2px;
}

.action-menu__row .action-menu__item {
    flex: 1;
    min-width: 0;
}

.action-menu__row .action-menu__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The plan you are looking at. Not a button, because there is nowhere to switch to. */
.action-menu__row.is-active .action-menu__item {
    cursor: default;
}

.action-menu__row.is-active .action-menu__name::before {
    content: "\2713\00a0";
    color: var(--accent);
}

.action-menu__row.is-active .action-menu__item:hover {
    background: none;
}

.action-menu__delete {
    flex: none;
    width: 34px;
    border: none;
    border-radius: 7px;
    background: none;
    font-size: 1.1rem;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
}

.action-menu__delete:hover {
    background: var(--danger-soft);
    color: var(--danger);
}

.action-menu__rule {
    margin: 4px 2px;
    border: none;
    border-top: 1px solid var(--line);
}

/* Names the group of rows under it, so the examples do not read as three more saved
   plans somebody has forgotten making. */
.action-menu__heading {
    margin: 6px 10px 2px;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
}

/* Saving is silent when it works, so the one time it does not has to say so plainly and
   keep saying it. Sits directly under the sketch, where the work it is about is. */
.save-warning {
    margin: 8px 2px 0;
    padding: 10px 12px;
    border: 1px solid var(--warn-line);
    border-left-width: 4px;
    border-radius: var(--radius);
    background: var(--warn-bg);
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--warn-ink);
}

/* ---- stage ----------------------------------------------------------- */

.stage-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}

.field {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 4px 10px;
    min-height: 44px;
}

.field label {
    font-size: 0.8rem;
    color: var(--muted);
    font-weight: 550;
}

.field__unit {
    font-size: 0.8rem;
    color: var(--muted);
}

/* 16px keeps iOS from zooming the page when an input takes focus. */
input[type="number"] {
    font: inherit;
    font-size: 16px;
    width: 4.5em;
    border: none;
    background: transparent;
    color: var(--ink);
    padding: 2px 0;
    min-width: 0;
}

input[type="number"]:focus {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 0 16px;
    border-radius: var(--radius);
    border: 1px solid var(--accent);
    background: var(--accent);
    color: var(--on-accent);
    font: inherit;
    font-weight: 550;
    text-decoration: none;
    cursor: pointer;
}

.button--ghost {
    background: var(--surface);
    color: var(--muted);
    border-color: var(--line);
}


.button--ghost:hover {
    color: var(--ink);
    border-color: var(--muted);
}

/* The one control in the stage bar, so it carries real contrast rather than the muted
   ghost it used to share with a second button beside it. */
.button--outline {
    background: var(--surface);
    color: var(--ink);
    border-color: var(--muted);
}

.button--outline:hover,
.button--outline[aria-expanded="true"] {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}

.shape-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 10px;
}

.shape-bar__label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    margin-right: 2px;
}

/* Typing the size, for the many yards that are a rectangle somebody already knows the
   dimensions of -- and the only route to a yard that does not need a pointer at all. */
.dims {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 10px;
}

.dims__label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    margin-right: 2px;
}

.dims__input {
    /* Room for four digits and a decimal, which covers any yard anyone will type. */
    width: 5.5rem;
    min-height: 40px;
    padding: 0 10px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    font: inherit;
    color: var(--ink);
}

.dims__input:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

.dims__times,
.dims__unit {
    font-size: 0.85rem;
    color: var(--muted);
}

.chip {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 550;
    cursor: pointer;
}

.chip:hover {
    border-color: var(--muted);
}

.chip.is-selected {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
}

.chip--ghost {
    color: var(--muted);
}

/* ---- map view ---------------------------------------------------------- */

.view-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 10px;
}

.view-bar__find {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1 1 260px;
    min-width: 0;
}

/* 16px for the same reason the number inputs carry it: anything smaller and iOS
   zooms the whole page when the box takes focus. */
.view-bar__find input[type="search"] {
    flex: 1 1 auto;
    min-width: 0;
    font: inherit;
    font-size: 16px;
    min-height: 44px;
    padding: 0 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--ink);
}

.view-bar__find input[type="search"]:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

.map-bar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: 6px 16px;
    margin-bottom: 10px;
    padding: 8px 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.map-bar__credit {
    margin: 0;
    min-width: 0;
    font-size: 0.75rem;
    color: var(--muted);
}

.map-bar__place {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--ink);
    font-weight: 550;
}

/* The Maps terms require the credit to stay visible, so it lives in the page rather
   than on the sketch, where the fade slider or a pan could carry it off. */
.map-bar__attribution {
    display: block;
}

.map-bar #map-remove {
    justify-self: end;
}

@media (max-width: 560px) {
    .map-bar {
        grid-template-columns: minmax(0, 1fr);
    }

    .map-bar #map-remove {
        justify-self: start;
    }

    /* Two chips and a search box will not share a row on a phone, and a wrapped row is
       another row of sketch below the fold. Give the box its own line deliberately. */
    .view-bar__find {
        flex-basis: 100%;
    }
}

.canvas-wrap {
    /* Matches the paper the canvas paints, so the sheet reads as one surface. */
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 8px;
    box-shadow: var(--shadow);
    /* The canvas fills this box exactly; panning and zooming move the drawing
       inside it, so there is nothing to scroll and no edge to run into. */
    overflow: hidden;
    height: min(58vh, 460px);
    height: min(58dvh, 460px);
    overscroll-behavior: contain;
}

#plan-canvas {
    display: block;
    /* Essential: lets a finger drag paint instead of scrolling the page. */
    touch-action: none;
    -webkit-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    cursor: crosshair;
}

#plan-canvas.is-tracing {
    cursor: cell;
}

.stage-note {
    margin: 8px 2px 0;
    font-size: 0.8rem;
    color: var(--muted);
}

/* ---- tools ----------------------------------------------------------- */

/* The material list is long, so it scrolls inside the panel rather than running
   on down the page and pushing the sketch out of view. */
.tool-scroll {
    max-height: 46vh;
    max-height: 46dvh;
    overflow-y: auto;
}

.tool-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 8px;
}

.tool {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 52px;
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    font: inherit;
    color: var(--ink);
    text-align: left;
    cursor: pointer;
    min-width: 0;
}

.tool:hover {
    border-color: var(--muted);
}

.tool.is-selected {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px var(--accent-soft);
}

.tool__swatch {
    flex: none;
    width: 30px;
    height: 30px;
    border-radius: 7px;
    border: 1px solid var(--swatch-line);
    display: grid;
    place-items: center;
    font-size: 15px;
    line-height: 1;
    /* See .total-row__swatch: the glyph belongs to the sheet, not to the page. */
    color: var(--paper-ink);
}

.tool--point .tool__swatch {
    border-radius: 50%;
    background-color: #fff !important;
}

.tool__label {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.tool__name {
    font-weight: 550;
    font-size: 0.9rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tool__meta {
    font-size: 0.72rem;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---- totals ---------------------------------------------------------- */

.totals__empty {
    margin: 0;
    color: var(--muted);
    font-size: 0.9rem;
}

.total-row {
    display: grid;
    grid-template-columns: 24px minmax(0, 1fr) auto;
    gap: 10px;
    align-items: start;
    padding: 10px 0;
    border-bottom: 1px solid var(--line);
}

.total-row__swatch {
    width: 22px;
    height: 22px;
    border-radius: 6px;
    border: 1px solid var(--swatch-line);
    display: grid;
    place-items: center;
    font-size: 12px;
    margin-top: 2px;
    /* A swatch is the colour the material paints on the sheet, and the symbol on it is
       drawn the same way there, so it takes the paper's ink rather than the page's --
       inheriting --ink put a pale glyph on a near-white eraser swatch in dark. */
    color: var(--paper-ink);
}

.total-row__name {
    font-weight: 550;
    font-size: 0.92rem;
}

.total-row__qty {
    font-size: 0.8rem;
    color: var(--muted);
}

.total-row__cost {
    font-variant-numeric: tabular-nums;
    font-size: 0.85rem;
    font-weight: 550;
    white-space: nowrap;
    text-align: right;
}

.depth-field {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    font-size: 0.78rem;
    color: var(--muted);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 2px 8px;
    min-height: 36px;
}

.depth-field input {
    width: 3.6em;
}

.totals__grand {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding-top: 12px;
}

.totals__grand-label {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
}

.totals__grand-value {
    font-size: 1.05rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.totals__disclaimer {
    margin: 6px 0 0;
    font-size: 0.74rem;
    color: var(--muted);
}

/* ---- reference & prose ----------------------------------------------- */

.notice {
    margin-top: 16px;
    padding: 12px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.reference {
    margin-top: 40px;
}

.reference__note {
    color: var(--muted);
    font-size: 0.88rem;
    margin-top: 0;
}

.table-scroll {
    overflow-x: auto;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface);
}

.reference__table {
    border-collapse: collapse;
    width: 100%;
    min-width: 520px;
    font-size: 0.88rem;
}

.reference__table th,
.reference__table td {
    text-align: left;
    padding: 10px 14px;
    border-bottom: 1px solid var(--line);
    font-weight: 400;
    white-space: nowrap;
}

.reference__table thead th {
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    font-weight: 600;
}

.reference__table tbody th {
    font-weight: 550;
}

.reference__table tbody tr:last-child th,
.reference__table tbody tr:last-child td {
    border-bottom: none;
}

.swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 4px;
    border: 1px solid var(--swatch-line);
    vertical-align: -2px;
    margin-right: 6px;
}

.prose {
    padding-top: 28px;
    max-width: 720px;
}

.prose p {
    color: var(--muted);
}

.prose h2 {
    font-size: 1.15rem;
    margin-top: 30px;
}

.guide-list {
    list-style: none;
    padding: 0;
    margin: 24px 0;
    display: grid;
    gap: 12px;
}

.guide-list li {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 16px;
}

/* The library is grouped, so a card's own heading sits a level below the group's. */
.guide-list h2,
.guide-list h3 {
    font-size: 1.05rem;
    margin-bottom: 4px;
}

.guide-group {
    margin-top: 32px;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
}

.guide-group + .guide-list {
    margin-top: 12px;
}

.guide-list p {
    margin: 0;
    font-size: 0.9rem;
}

.guide-list__status {
    margin-top: 8px !important;
    font-size: 0.72rem !important;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--accent);
}

/* ---- wide screens ---------------------------------------------------- */

@media (min-width: 900px) {
    /* Far more room for the sketch once there is a second column. */
    .canvas-wrap {
        height: min(78vh, 880px);
        height: min(78dvh, 880px);
    }

    .planner {
        grid-template-columns: minmax(0, 1fr) 340px;
        grid-template-rows: auto 1fr;
        align-items: start;
        grid-template-areas:
            "stage tools"
            "stage totals";
    }

    /* The two right-hand panels together match the sketch, and each scrolls inside
       itself, so the material list never pushes the sketch off the screen. */
    .planner__tools {
        display: flex;
        flex-direction: column;
        /*
         * The two panels split the column roughly evenly, and together they come to about
         * the height of the sketch beside them.
         *
         * The materials used to take twice the room the totals did, which had the totals
         * showing a row and a half: the one number the whole site exists to produce,
         * behind a scrollbar. The list of materials is a picker that scrolls by design and
         * loses nothing by being shorter; the totals are the answer, and are read.
         */
        max-height: min(40vh, 440px);
        max-height: min(40dvh, 440px);
    }

    .tool-scroll {
        flex: 1;
        overscroll-behavior: contain;
        /* The column's own height decides this now, not the phone cap. */
        max-height: none;
        min-height: 0;
        /* Room for the scrollbar so the chips do not sit under it. */
        padding-right: 4px;
    }

    .planner__totals {
        display: flex;
        flex-direction: column;
        /* See .planner__tools above for why these two are the size they are. A cap, not a
           height: a plan with two materials on it makes a short panel rather than a tall
           one with a hole in the bottom.

           The larger share, because the rows here are not a uniform height. A material
           bought by the yard carries a depth box and the bagged-against-bulk comparison,
           which is 200px of row on its own against 60px for a tree. */
        max-height: min(54vh, 580px);
        max-height: min(54dvh, 580px);
    }

    .planner__totals > div {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding-right: 4px;
    }

    /* The heading used to be pinned to the left edge here, flush with the sketch below it.
       On a wide screen that put a 720px column against the left of a 1440px page, which
       read as text that had slid off to one side rather than as a heading. It centres over
       the planner now; the auto margins on the base rules are all that is needed for that,
       so the override that used to sit here is gone rather than set back to auto. */

    /* Moves the pair right as a group. On a phone the row wraps, and an auto
       margin there just strands them at opposite ends of their lines. */
    .stage-bar .menu-anchor {
        margin-left: auto;
    }
}

.mode-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
}

.mode-bar .chip {
    flex: 1 1 auto;
    justify-content: center;
    min-height: 38px;
}

.seg {
    display: inline-flex;
    gap: 0;
}

.seg .chip:first-child {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.seg .chip:last-child {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    margin-left: -1px;
}

.chip:disabled {
    opacity: 0.4;
    cursor: default;
}

.shape-help {
    margin: 0 2px 10px;
    font-size: 0.78rem;
    color: var(--muted);
}

/* ---- on-canvas controls ---------------------------------------------- */

.canvas-wrap {
    position: relative;
}

.canvas-hint {
    position: absolute;
    left: 10px;
    bottom: 10px;
    margin: 0;
    max-width: calc(100% - 76px);
    padding: 5px 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.9);
    border: 1px solid var(--paper-line);
    font-size: 0.76rem;
    color: var(--paper-muted);
    pointer-events: none;
}

.canvas-actions {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    gap: 6px;
}

.canvas-btn {
    min-height: 36px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: #fff;
    font: inherit;
    font-size: 0.82rem;
    font-weight: 550;
    cursor: pointer;
    box-shadow: var(--shadow-chip);
}

.canvas-btn--quiet {
    background: var(--paper-surface);
    border-color: var(--paper-line);
    color: var(--paper-muted);
}

/* Sits at the tapped wall, like the reference sketch's context menu. */
.wall-menu {
    position: absolute;
    z-index: 6;
    display: flex;
    flex-direction: column;
    min-width: 132px;
    padding: 4px;
    border-radius: 10px;
    border: 1px solid var(--paper-line);
    background: var(--paper-surface);
    box-shadow: var(--shadow-float);
    transform: translate(-50%, -50%);
}

.wall-menu__item {
    appearance: none;
    border: none;
    background: none;
    font: inherit;
    font-size: 0.85rem;
    text-align: left;
    padding: 9px 12px;
    border-radius: 7px;
    color: var(--paper-ink);
    cursor: pointer;
    min-height: 40px;
}

.wall-menu__item:hover {
    background: var(--accent-soft);
    color: var(--accent);
}

/* Something under the pointer can be dragged. */
#plan-canvas.is-grabbable {
    cursor: grab;
}

#plan-canvas.is-grabbable:active {
    cursor: grabbing;
}

.zoom-bar {
    position: absolute;
    right: 10px;
    bottom: 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    z-index: 5;
}

.zoom-btn {
    width: 38px;
    height: 38px;
    border-radius: 9px;
    border: 1px solid var(--paper-line);
    background: rgba(255, 255, 255, 0.94);
    color: var(--paper-ink);
    font: inherit;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(34, 32, 28, 0.14);
}

.zoom-btn--fit {
    font-size: 0.72rem;
}

.zoom-btn:hover {
    border-color: var(--paper-muted);
}

#plan-canvas.is-panning {
    cursor: grabbing;
}

/* In shape-editing mode the sheet itself can be dragged around. */
#plan-canvas.is-editing {
    cursor: grab;
}

.wave-fields {
    display: grid;
    gap: 4px;
    margin-bottom: 10px;
}

.wave-field {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8rem;
    color: var(--muted);
}

.wave-field > span:first-child {
    min-width: 3.6em;
}

.wave-field input[type="range"] {
    flex: 1;
    min-width: 0;
    accent-color: var(--accent);
}

.wave-field__value {
    min-width: 3.2em;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
    font-weight: 550;
}

/* ---- grouped material picker ------------------------------------------ */

.tool-group {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.tool-group__head {
    border-radius: var(--radius);
}

.tool-group.holds-selection {
    border-color: var(--accent);
}

.tool-group__head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 52px;
    padding: 8px 10px;
    border: none;
    background: none;
    font: inherit;
    color: var(--ink);
    text-align: left;
    cursor: pointer;
}

.tool-group__head:hover {
    background: var(--accent-soft);
}

.tool-group__swatches {
    display: flex;
    flex: none;
}

.tool-group__chip {
    width: 18px;
    height: 30px;
    border: 1px solid var(--swatch-line);
    margin-right: -6px;
    border-radius: 5px;
}

.tool-group__chip:first-child {
    border-radius: 7px 5px 5px 7px;
}

.tool-group__chip:last-child {
    margin-right: 0;
    border-radius: 5px 7px 7px 5px;
}

.tool-group__label {
    display: flex;
    flex: 1;
    min-width: 0;
    flex-direction: column;
}

.tool-group__name {
    font-weight: 550;
    font-size: 0.9rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tool-group__pick {
    font-size: 0.72rem;
    color: var(--accent);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tool-group__count {
    flex: none;
    font-size: 0.72rem;
    color: var(--muted);
    background: var(--bg);
    border-radius: 999px;
    padding: 1px 7px;
}

.tool-group.is-open .tool-group__head,
.tool-group__head[aria-expanded="true"] {
    background: var(--accent-soft);
}

.tool-group__head[aria-expanded="true"] .tool-group__count {
    background: var(--accent-soft);
    color: var(--accent);
}

.tool-group__items {
    position: fixed;
    z-index: 40;
    display: grid;
    gap: 6px;
    padding: 8px;
    max-height: min(52vh, 420px);
    max-height: min(52dvh, 420px);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-pop);
}

/* Inside a group the border would double up with the group's own. */
.tool-group__items .tool {
    border-color: transparent;
    background: var(--bg);
}

.tool-group__items .tool.is-selected {
    background: var(--surface);
}

.mode-bar__label {
    align-self: center;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    margin-right: 2px;
}

/* ---- phones ----------------------------------------------------------- */

@media (max-width: 899px) {
    /* The sketch is what someone came for, so it goes directly under the shape
       buttons and the paragraph explaining them moves below it. */
    .planner__stage {
        display: flex;
        flex-direction: column;
    }

    .canvas-wrap {
        flex: none;
    }

    .shape-help {
        order: 1;
        margin: 10px 2px 0;
    }

    /* The photo's own controls follow the help text below the sketch, and for the same
       reason: 200px of sliders above it puts the sketch itself under the fold. */
    .map-bar {
        order: 1;
        margin: 10px 2px 0;
    }

    /* Every pixel above the sketch is a pixel of sketch below the fold. The heading is
       the only thing that sits above it, and it says so rather than relying on the
       default: an unnumbered child sorts to the front, not the back. */
    .intro {
        order: 0;
        padding-top: 20px;
    }

    /* The planner is what the page is for, so on a phone it comes before the
       paragraph describing it. The DOM order is unchanged. */
    main {
        display: flex;
        flex-direction: column;
    }

    .planner {
        order: 1;
        padding-top: 14px;
    }

    .ad-slot[data-ad-placement="planner-bottom"] {
        order: 2;
    }

    .intro-lede {
        order: 3;
        margin-top: 24px;
    }

    noscript,
    .reference {
        order: 4;
    }

    /* Left out of this list, the questions defaulted to order 0 and sorted above
       everything numbered, which landed them between the heading and the sketch. */
    .faq {
        order: 5;
    }

    /* Last, after the content, exactly as it falls on a wide screen. */
    .ad-slot[data-ad-placement="content-bottom"] {
        order: 6;
    }

    /* Six chips that all grow land two per row. Letting them size to their text
       packs the run bar into two rows instead of three. */
    #line-mode-bar .chip {
        flex: 0 1 auto;
    }
}

/* A phone held sideways has very little height, and the sketch was getting the
   worst of it. */
@media (max-width: 899px) and (orientation: landscape) {
    .intro {
        padding-top: 14px;
    }

    .canvas-wrap {
        height: min(72vh, 420px);
        height: min(72dvh, 420px);
    }

    .tool-scroll {
        max-height: 62vh;
        max-height: 62dvh;
    }
}

/* ---- touch targets ---------------------------------------------------- */

/* A finger is about 44px wide. These controls were sized for a cursor. */
@media (pointer: coarse) {
    .chip,
    .mode-bar .chip,
    .canvas-btn,
    .wall-menu__item,
    .depth-field {
        min-height: 44px;
    }

    .zoom-btn {
        width: 44px;
        height: 44px;
    }

    .wave-field input[type="range"] {
        height: 44px;
    }

    .brand {
        min-height: 44px;
    }

    .site-footer a {
        display: inline-block;
        padding: 10px 0;
    }

    /* The box was 44px but the input inside it was 29px, so most of the
       control was not actually tappable. */
    .field {
        padding-block: 0;
        min-height: 46px;
    }

    .field input[type="number"] {
        align-self: stretch;
    }
}

/* The full wording ran the shape bar to three rows on a phone, pushing the
   sketch well below the fold. A shared "Redraw" label carries the verb there. */
.chip__short {
    display: none;
}

@media (max-width: 560px) {
    .chip__full {
        display: none;
    }

    .chip__short {
        display: inline;
    }

    /* Sharing a row with the chips, this label pushed them onto a fourth line.
       On its own line it costs 18px and saves about 90. */
    .shape-bar__label {
        flex-basis: 100%;
        margin-bottom: -2px;
    }
}

/* Ad units. Kept well away from the sketch and the tool panel: an ad next to a
   control someone is dragging is both an AdSense placement violation and a way
   to lose the click they meant to make. */
.ad-slot {
    display: block;
    max-width: 970px;
    margin: 32px auto 0;
    text-align: center;
}

.ad-slot__label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.7rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--muted);
}

/* Reserving the height stops a late-arriving ad from shoving the page down
   under someone's finger. */
.ad-slot .adsbygoogle {
    display: block;
    min-height: 100px;
}

/* Google reports an unsold unit by stamping the <ins>; collapse the label with
   it rather than leaving a labelled blank. */
.ad-slot:has(.adsbygoogle[data-ad-status="unfilled"]) {
    display: none;
}

/* ---- material strip (phones) ------------------------------------------ */

/* Empty and out of the way on a wide screen: the picker only moves in here when the
   layout goes single column. */
.material-bar {
    display: none;
}

@media (max-width: 899px) {
    /* Picker first, then how the armed material goes down: one cluster under the sketch
       instead of the paint modes sitting a paragraph of help further down the page. */
    .material-bar {
        display: flex;
        flex-direction: column;
        gap: 10px;
        min-width: 0;
        margin-top: 10px;
    }

    /* The column's gap spaces these; their own margin would double it. */
    .material-bar .mode-bar,
    .material-bar .wave-fields {
        margin-bottom: 0;
    }

    /* One row that scrolls sideways, sitting right under the sketch. Down the page in
       the tools panel it was a scroll away, and every pick meant scrolling back up to
       see what it did. */
    .material-bar .tool-grid {
        display: flex;
        min-width: 0;
        max-width: 100%;
        gap: 8px;
        overflow-x: auto;
        padding-bottom: 4px;
        overscroll-behavior-x: contain;
        scrollbar-width: thin;
    }

    .material-bar .tool-group,
    .material-bar .tool {
        flex: 0 0 auto;
        max-width: 60vw;
    }

    .material-bar .tool-group__head,
    .material-bar .tool {
        min-height: 52px;
        white-space: nowrap;
    }

    /* Prices belong in the dropdown and the reference table, not in a row that has to
       stay narrow enough to fit several materials on screen at once. */
    .material-bar > .tool-grid > .tool .tool__meta {
        display: none;
    }

    /* The panel keeps the paint modes and the help text, but its heading would now sit
       above an empty space where the picker used to be. Moved off screen rather than
       removed, so the section still announces itself to a screen reader. */
    .planner__tools .panel__title {
        position: absolute;
        left: -9999px;
    }

    .tool-scroll {
        max-height: none;
        overflow-y: visible;
    }
}

/* ---- guide articles ---------------------------------------------------- */

.guide-crumb {
    margin: 0 0 6px;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

/* The opening paragraph carries the whole promise of the page, so it reads a step up
   from the body without shouting. */
.guide-lede {
    font-size: 1.05rem;
    line-height: 1.6;
}

.prose ul,
.prose ol {
    color: var(--muted);
    padding-left: 20px;
    margin: 14px 0;
}

.prose li {
    margin-bottom: 8px;
}

.prose li strong,
.prose p strong {
    color: var(--ink);
}

.prose .table-scroll {
    margin: 18px 0;
}

/* The one line of arithmetic each guide is really about. */
.formula {
    margin: 18px 0;
    padding: 14px 16px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius);
    line-height: 1.9;
}

.formula code {
    font-size: 0.98rem;
    font-weight: 600;
    color: var(--ink);
}

.guide-cta {
    margin: 26px 0 18px;
}

.guide-list h2 a {
    text-decoration: none;
}

.guide-list h2 a:hover {
    text-decoration: underline;
}

/* A key on the keyboard, in the help text under the sketch. */
kbd {
    display: inline-block;
    padding: 1px 5px;
    border: 1px solid var(--line);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: var(--surface);
    font-family: inherit;
    font-size: 0.85em;
    font-weight: 600;
    line-height: 1.4;
    color: var(--ink);
    white-space: nowrap;
}

/* ---- FAQ ---------------------------------------------------------------- */

.faq__list {
    margin: 0;
}

.faq__list dt {
    font-weight: 650;
    color: var(--ink);
    margin-top: 20px;
}

.faq__list dd {
    margin: 6px 0 0;
    color: var(--muted);
}


/* ---- printed sheet ------------------------------------------------------ */

/* Built by the planner only while a print is in flight, so it never shows on screen.
   Printing the page itself would print the sketch cropped to the current pan and zoom,
   wrapped in the header, the tool panel and an ad; this is the sketch on its own. */
.print-sheet {
    display: none;
}

.print-sheet__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid #ddd;
    padding-bottom: 6px;
}

.print-sheet__brand {
    display: inline-flex;
    align-items: center;
}

.print-sheet__mark {
    display: block;
    height: 22px;
    width: auto;
}

.print-sheet__site,
.print-sheet__foot {
    color: #666;
    font-size: 0.78rem;
}

.print-sheet__meta {
    margin: 8px 0 10px;
    color: #444;
    font-size: 0.85rem;
}

.print-sheet__plan {
    display: block;
    margin: 0 auto;
    max-width: 100%;
    /* A tall yard is taller than the page it is printed on unless something stops it, and
       break-inside then splits it across two sheets. This ceiling is the thing that stops
       it, so it is set here rather than only in the orientation query below: a phone whose
       print path never resolves that query still gets a sketch that fits. 13cm clears the
       shortest page the sheet can land on -- landscape Letter, about 19cm between the
       margins -- with the brand line, the size line and the date taking the rest. */
    max-height: 13cm;
    width: auto;
    height: auto;
    border: 1px solid #bbb;
}

/* A portrait page has 25cm rather than 19cm, so the sketch can be half again as tall on
   the browsers that say which way up the paper is. */
@media print and (orientation: portrait) {
    .print-sheet__plan {
        max-height: 16cm;
    }
}

/* The material list under the drawing: what to buy, and the key to what is on the sheet. */
.print-sheet__list {
    margin: 12px 0 0;
    /* The list may run onto a second page; the drawing above it must not be split, and
       neither must a row of the table. */
    break-inside: auto;
}

.print-sheet__list table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.78rem;
}

.print-sheet__list th,
.print-sheet__list td {
    text-align: left;
    vertical-align: top;
    padding: 4px 8px 4px 0;
    border-bottom: 1px solid #ddd;
    break-inside: avoid;
}

.print-sheet__list thead th {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #666;
    border-bottom: 1px solid #999;
}

.print-sheet__list tfoot th,
.print-sheet__list tfoot td {
    border-bottom: none;
    border-top: 1px solid #999;
    padding-top: 6px;
    font-weight: 700;
}

.print-sheet__cost {
    text-align: right;
    white-space: nowrap;
}

/* The row's own colour, so the list doubles as the key to the drawing. Printers drop
   backgrounds by default, and this is the one background on the sheet that carries
   meaning rather than decoration, so it asks to be kept. */
.print-sheet__swatch {
    display: inline-block;
    width: 9px;
    height: 9px;
    margin-right: 6px;
    border: 1px solid rgba(0, 0, 0, 0.35);
    border-radius: 2px;
    vertical-align: baseline;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}

.print-sheet__note {
    margin: 8px 0 0;
    color: #666;
    font-size: 0.7rem;
}

.print-sheet__foot {
    margin: 8px 0 0;
    text-align: right;
}

@media print {
    /* Everything except the sheet, including the header, the ads and the planner itself.
       Hiding by class would mean revisiting this list every time the page grows a section. */
    body > *:not(#print-sheet) {
        display: none !important;
    }

    .print-sheet {
        display: block;
        color: #000;
        background: #fff;
    }

    /* A page break through the drawing makes both halves useless. */
    .print-sheet__plan {
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* A long list is allowed onto a second page, but its heading row goes with it, so a
       column of numbers on page two still says which column it is. */
    .print-sheet__list thead {
        display: table-header-group;
    }
}

@page {
    margin: 14mm;
}

/* ---- guide calculators -------------------------------------------------- */

/* The answer to the question in the page's own headline, above the prose that explains it.
   Someone who came for the number gets the number; someone who wants the reasoning reads on. */
.calc {
    margin: 24px 0 28px;
    padding: 18px 18px 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.calc__heading {
    margin: 0 0 14px;
    font-size: 1.05rem;
}

.calc__form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
}

.calc__row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
}

.calc__field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.calc__field label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
}

/* Page chrome, not part of a sketch: it takes the page's surface and ink. It asked for
   --paper before that token existed, which resolved to nothing and left the card's own
   white showing through -- correct by accident in light, and a near-white box under pale
   text once the token was real and the page could go dark. */
.calc__field input {
    width: 6rem;
    min-height: 42px;
    padding: 0 10px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    font: inherit;
    color: var(--ink);
}

.calc__field input:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

/* Sits on the input's baseline rather than the label's, so a row of fields lines up. */
.calc__times {
    align-self: center;
    padding-top: 18px;
    color: var(--muted);
}

/* Under the field it belongs to, so a row of boxes does not need a legend explaining
   which of them is in feet and which is in inches. */
.calc__unit {
    font-size: 0.72rem;
    color: var(--muted);
}

.calc__out {
    display: block;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--line);
    font-size: 0.95rem;
    line-height: 1.55;
    color: var(--ink);
}

.calc__out:empty {
    display: none;
}

.calc__link {
    margin: 12px 0 0;
    font-size: 0.85rem;
    color: var(--muted);
}

@media (max-width: 599px) {
    /* Two fields to a row on a phone rather than one long scroll of them. */
    .calc__field input {
        width: 5rem;
    }
}

/* ---- where the material comes from -------------------------------------- */

/* Prices are quoted for somewhere, and this says where. Above the totals rather than
   buried under them: it changes every number below it. */
.region-field {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

.region-field__label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    white-space: nowrap;
}

.region-field select {
    flex: 1;
    min-width: 0;
    min-height: 40px;
    padding: 0 8px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    font: inherit;
    color: var(--ink);
}

.region-field select:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

/* The two ways the same pile is bought, under the material it belongs to. Bagged first
   because that is what people picture, then the number that changes their mind. */
.total-row__buying {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px dashed var(--line);
}

.total-row__route {
    font-size: 0.76rem;
    line-height: 1.45;
    color: var(--muted);
}

/* Marked rather than merely listed: the whole point of showing both is that one of them
   is often half the price, and that is easy to skim past in two grey lines. */
.total-row__route.is-better {
    font-weight: 600;
    color: var(--accent);
}

.total-row__advice {
    margin-top: 2px;
    font-size: 0.72rem;
    line-height: 1.4;
    color: var(--muted);
}

/* The size of a placed item, which belongs to the item rather than to the grid: a mature
   oak and a rose bush are one item and one price each, and nothing like the same size. */
#item-size-field {
    align-items: center;
}

#item-delete {
    margin-left: auto;
}

/* ---- address suggestions ------------------------------------------------ */

/* The list hangs under the address box rather than pushing the bar around, so the sketch
   below it does not jump every time somebody types a letter. */
.suggest {
    position: relative;
    flex: 1;
    min-width: 0;
}

.suggest__list {
    position: absolute;
    z-index: 45;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    margin: 0;
    padding: 4px;
    list-style: none;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-pop);
}

.suggest__option {
    padding: 10px 12px;
    border-radius: 7px;
    font-size: 0.9rem;
    line-height: 1.35;
    color: var(--ink);
    cursor: pointer;
}

/* Hover and the keyboard highlight are the same state deliberately: with both a mouse and
   arrow keys in play, two different highlights on one list is two answers to "what does
   Enter do now". */
.suggest__option:hover,
.suggest__option.is-active {
    background: var(--accent-soft);
}

/* Fill sits beside Replace and Add layer but is not one of them: those two are a choice of
   what happens to what is already there, and this is a choice of drag versus tap. The gap
   says so without a second label. */
.mode-bar__fill {
    margin-left: 8px;
}

/* A bucket cursor, so it is obvious before the tap that a tap is about to do rather a lot. */
#plan-canvas.is-filling {
    cursor: cell;
}

/* Privacy and Contact sit on one line with room between them, rather than running together
   as one long string of underlined words. */
.site-footer__links {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}
