/*
    Minimal styling for the public site. Deliberately small and hand-written: this is a
    photo-led site for a woodworking studio, so the job is to get out of the photographs'
    way, not to import a framework.

    Colours are drawn from the work itself - hard maple and black epoxy - rather than picked
    from a palette generator.
*/

:root {
    --maple: #f5f0e6;
    --maple-deep: #e8dfcc;
    --ink: #1a1714;
    --ink-soft: #4a423a;
    --epoxy: #12100e;
    --sapele: #8c4a2f;
    --rule: #d8cfbb;
    --max-width: 68rem;
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--maple);
    color: var(--ink);
    font-family: Georgia, "Iowan Old Style", "Palatino Linotype", serif;
    font-size: 1.0625rem;
    line-height: 1.65;
}

main {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 2rem 1.25rem 4rem;
}

h1,
h2,
h3 {
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0 0 0.5em;
}

h1 {
    font-size: clamp(2rem, 5vw, 3rem);
}

h2 {
    font-size: clamp(1.25rem, 3vw, 1.5rem);
}

p {
    margin: 0 0 1rem;
    max-width: 62ch; /* long measures are hard to read; cap the line length */
}

a {
    color: var(--sapele);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.15em;
}

a:hover,
a:focus-visible {
    color: var(--epoxy);
}

/* A visible focus ring is an accessibility requirement, not a style choice (WCAG 2.4.7). */
:focus-visible {
    outline: 3px solid var(--sapele);
    outline-offset: 2px;
}

/*
    Blazor's <FocusOnNavigate> moves focus to the <h1> after each navigation, which is good
    for screen-reader users but gives the heading tabindex="-1" and draws a focus ring around
    it. The ring belongs on things the user actually focused, not on a heading the framework
    focused on their behalf.

    Scoped to tabindex="-1" so genuinely interactive elements keep their ring.
*/
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none;
}

/* ---------------------------------------------------------------- site chrome */

.site-header {
    border-bottom: 1px solid var(--rule);
    background: var(--maple-deep);
}

.site-header__inner {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 1rem 1.25rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 2rem;
}

.site-header__brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-weight: 700;
    text-decoration: none;
    color: var(--ink);
}

.site-header__brand img {
    display: block;
    width: auto;
    height: 3rem;
}

.site-nav {
    display: flex;
    gap: 1.5rem;
    margin-left: auto;
}

.site-footer {
    border-top: 1px solid var(--rule);
    margin-top: 3rem;
    padding: 2rem 1.25rem;
    color: var(--ink-soft);
    font-size: 0.9375rem;
}

.site-footer__inner {
    max-width: var(--max-width);
    margin: 0 auto;
}

/* ------------------------------------------------------- home: featured work

   The photographs on the front page. Deliberately the same grid mechanics as the gallery
   below — auto-fit columns, natural image ratios, no cropping — because they are the same
   thing shown in two places, and two subtly different photo grids is how a small site starts
   looking like it was built by two people who never spoke.

   What differs is density: four pieces rather than the whole portfolio, and the caption sits
   tighter, because this section's job is to prove the work is real and send the visitor to
   the gallery, not to be the gallery. */

.home-intro {
    font-size: 1.125rem;
    color: var(--ink-soft);
    max-width: 42rem;
    margin-bottom: 2.5rem;
}

.featured-work {
    margin-bottom: 3.5rem;
}

.featured-grid {
    list-style: none;
    margin: 0 0 1.5rem;
    padding: 0;
    display: grid;
    gap: 2rem;
    /*
        22rem, and the exact number matters — it was measured in the browser, not guessed.

        The content column is 68rem wide, so at 20rem this grid resolves to THREE columns and four
        pieces render as a row of three with a lonely fourth beneath it. 22rem is the first value
        that tips it to two, giving a 2×2 block with the photographs shown large — which is what
        this section is for, since the pictures are the argument the front page makes. The gallery
        is where the full set gets browsed small.

        Still collapses to a single column on a phone, via the min(100%, …).
    */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
    /* NOT align-items: start, which is what the gallery below uses. The gallery is a long
       scrolling page where tiles of different heights read as a natural sequence; four tiles
       in a single strip with wildly different heights read as a broken layout, because there
       is nothing after them to establish the rhythm. The fixed image box below is what makes
       stretch work. */
}

/* The whole tile is the link — photograph and caption together. A link wrapped around only
   the title gives a mouse user a small target and a touch user a smaller one, next to a
   large photograph that looks clickable and is not. */
.featured-item a {
    display: block;
    text-decoration: none;
    color: inherit;
}

.featured-item a:hover .featured-title,
.featured-item a:focus-visible .featured-title {
    text-decoration: underline;
}

/* Focus lands on the anchor, which wraps the image — so the ring must sit outside it or it
   is drawn underneath the photograph and effectively invisible. */
.featured-item a:focus-visible {
    outline: 3px solid var(--ink);
    outline-offset: 4px;
    border-radius: 2px;
}

.featured-item figure {
    margin: 0;
}

/*
    A FIXED BOX WITH object-fit: contain — and the `contain` is the whole point.

    These four photographs are a mix of portrait and landscape, from a phone, in a garden and on a
    workbench. Left at their natural heights in a four-across strip the row goes ragged and the
    front page looks broken.

    `cover` would square them up neatly and is exactly what must NOT happen: it crops, and cropping
    a sign cuts off the lettering that is the entire point of the piece. (It did precisely that to
    the Ash + Ember sign once already — see .gallery-item img.)

    `contain` fits the whole photograph inside a consistent box and letterboxes the remainder
    against the maple background. Every tile is the same height, every row lines up, and not one
    pixel of anybody's name is lost.
*/
.featured-item img {
    display: block;
    width: 100%;
    height: 20rem;
    object-fit: contain;
    object-position: center;
    background: var(--maple-deep);
    border-radius: 2px;
}

.featured-item figcaption {
    padding-top: 0.7rem;
}

.featured-title {
    display: block;
    font-weight: 600;
    margin-bottom: 0.15rem;
}

.featured-summary {
    display: block;
    color: var(--ink-soft);
    font-size: 0.9375rem;
}

.featured-more {
    margin: 0;
}

/* ---------------------------------------------------------------- gallery */

.gallery-intro {
    margin-bottom: 2.5rem;
}

.gallery-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 2.5rem;
    /* auto-fit rather than fixed columns: one column on a phone, more as room allows,
       without a media-query ladder to maintain. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
    /* Images keep their natural ratios, so tiles vary in height. Align to the top rather
       than stretching, so captions sit directly under their photograph. */
    align-items: start;
}

.gallery-item figure {
    margin: 0;
}

.gallery-item img {
    display: block;
    width: 100%;
    height: auto;
    background: var(--maple-deep);
    border-radius: 2px;
    /*
        No forced aspect-ratio and no object-fit: cover. A uniform frame looks tidier, but it
        crops - and on a sign, cropping cuts off the lettering that is the whole point of the
        piece. (It did exactly that to the Ash + Ember sign.) Each photograph renders at its
        true ratio; the width/height attributes come from the stored dimensions, so the
        browser still reserves the correct box and the page does not reflow.

        align-items: start on the grid keeps rows tidy despite the varying heights.
    */
}

.gallery-item figcaption {
    padding-top: 0.85rem;
}

.gallery-item h2 {
    margin-bottom: 0.25rem;
}

.gallery-item p {
    margin: 0;
    color: var(--ink-soft);
}

/*
    ---------------------------------------------------------------- studio admin

    The staff area. Same palette as the public site - it is the same business, and a wildly
    different admin skin would mean maintaining two visual languages for two people.

    What is deliberately different: denser type, a wider measure, and controls that look like
    controls. The public site's job is to get out of the photographs' way; this one's job is to
    be quick to read at the end of a working day.
*/

.admin-header {
    border-bottom: 2px solid var(--epoxy);
    background: var(--maple-deep);
}

.admin-header__inner,
.admin-main,
.admin-footer {
    max-width: 78rem; /* wider than the public --max-width: tables and a sidebar need the room */
    margin: 0 auto;
    padding-inline: 1.25rem;
}

.admin-header__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 2rem;
    padding-block: 0.75rem;
}

.admin-header__brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-weight: 700;
    text-decoration: none;
    color: var(--ink);
}

.admin-header__brand img {
    display: block;
    width: auto;
    height: 2.25rem;
}

.admin-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
    margin-left: auto;
}

.admin-main {
    padding-block: 2rem 4rem;
}

.admin-footer {
    border-top: 1px solid var(--rule);
    padding-block: 1.25rem;
    color: var(--ink-soft);
    font-size: 0.9375rem;
}

.admin-lede {
    color: var(--ink-soft);
    max-width: 60ch;
}

/* --------------------------------------------------- dashboard cards */

.admin-cards {
    list-style: none;
    margin: 0 0 2rem;
    padding: 0;
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
}

.admin-card {
    border: 1px solid var(--rule);
    border-radius: 3px;
    background: #fff;
    padding: 1rem 1.1rem;
}

.admin-card h3 {
    font-size: 1rem;
    margin-bottom: 0.35rem;
}

.admin-card__figure {
    margin: 0;
    font-size: 2rem;
    line-height: 1.1;
}

.admin-card__unit,
.admin-card__detail {
    font-size: 0.875rem;
    color: var(--ink-soft);
}

.admin-card__detail {
    margin: 0.25rem 0 0;
}

/* --------------------------------------------------- forms and controls */

.admin-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem;
    margin-bottom: 1.5rem;
    padding: 1rem;
    border: 1px solid var(--rule);
    border-radius: 3px;
    background: var(--maple-deep);
}

.admin-field {
    margin-bottom: 1.25rem;
}

.admin-field label {
    display: block;
    font-weight: 700;
    margin-bottom: 0.3rem;
}

/*
    Not `input[type="text"]`. Blazor's <InputText> renders a bare <input> with no type attribute -
    which is a text input as far as the browser is concerned, and invisible to that selector as far
    as CSS is concerned. The title, slug and tags fields rendered at the browser's default width
    while the hand-written <input type="text"> next to them filled its container. Every test was
    green; a screenshot found it in a second.
*/
.admin-field input:not([type="hidden"]),
.admin-field select,
.admin-field textarea {
    width: 100%;
    max-width: 42rem;
    padding: 0.45rem 0.55rem;
    border: 1px solid var(--ink-soft);
    border-radius: 2px;
    background: #fff;
    color: var(--ink);
    font: inherit;
    font-size: 1rem;
}

.admin-field textarea {
    font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
    font-size: 0.9375rem;
    line-height: 1.6;
    resize: vertical;
}

.admin-hint {
    margin: 0.35rem 0 0;
    font-size: 0.875rem;
    color: var(--ink-soft);
    max-width: 60ch;
}

.admin-button {
    display: inline-block;
    padding: 0.5rem 1.1rem;
    border: 1px solid var(--ink);
    border-radius: 2px;
    background: #fff;
    color: var(--ink);
    font: inherit;
    font-size: 1rem;
    text-decoration: none;
    cursor: pointer;
}

.admin-button--primary {
    background: var(--epoxy);
    border-color: var(--epoxy);
    color: var(--maple);
}

/*
    Destructive actions read as destructive. Not red-on-white by default, though: an outlined button
    beside a filled primary one keeps "delete" from competing with "save" for attention on a page
    where saving is what you are usually there to do. It fills in only once you are on the
    confirmation step, where it IS the primary action.
*/
.admin-button--danger {
    border-color: #8c2f2f;
    color: #8c2f2f;
}

.admin-confirm .admin-button--danger {
    background: #8c2f2f;
    border-color: #8c2f2f;
    color: #fff;
}

.admin-button--danger:hover {
    border-color: #6d2424;
}

.admin-confirm {
    margin: 0.75rem 0 1.5rem;
    padding: 1rem;
    border: 1px solid #8c2f2f;
    border-radius: 2px;
    background: #fdf6f4;
}

.admin-confirm p {
    margin-top: 0;
}

.admin-confirm .admin-form {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    align-items: center;
}

.admin-button:hover {
    border-color: var(--sapele);
}

/* --------------------------------------------------- editor layout */

.admin-editor-grid {
    display: grid;
    gap: 2rem;
    grid-template-columns: minmax(0, 3fr) minmax(0, 1fr);
    align-items: start;
}

@media (max-width: 60rem) {
    .admin-editor-grid {
        grid-template-columns: 1fr;
    }
}

.admin-sidebar {
    border: 1px solid var(--rule);
    border-radius: 3px;
    background: var(--maple-deep);
    padding: 1rem 1.1rem;
}

.admin-sidebar h2 {
    font-size: 1.0625rem;
}

.admin-sidebar h3 {
    font-size: 0.9375rem;
    margin-top: 1.25rem;
}

.admin-breadcrumb {
    font-size: 0.875rem;
    margin-bottom: 0.5rem;
}

/* --------------------------------------------------- notices */

.admin-notice {
    margin: 0 0 1.5rem;
    padding: 0.75rem 1rem;
    border-left: 4px solid var(--sapele);
    background: var(--maple-deep);
    max-width: none;
}

.admin-notice--ok {
    border-left-color: #2f6b3a;
}

.admin-notice--error {
    border-left-color: #a3231b;
}

.admin-notice h2 {
    font-size: 1rem;
    margin-bottom: 0.35rem;
}

.admin-notice ul {
    margin: 0;
    padding-left: 1.25rem;
}

/* --------------------------------------------------- tables */

.admin-table {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
}

.admin-table caption {
    text-align: left;
    color: var(--ink-soft);
    font-size: 0.875rem;
    padding-bottom: 0.5rem;
}

.admin-table th,
.admin-table td {
    border-bottom: 1px solid var(--rule);
    padding: 0.6rem 0.75rem 0.6rem 0;
    vertical-align: top;
}

.admin-table thead th {
    border-bottom-width: 2px;
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/*
    State is spelled out in the cell as well as coloured. Colour alone fails WCAG 1.4.1, and
    "is this live?" is the one question the list exists to answer - so the answer must survive
    a monochrome screen and a colour-blind reader.
*/
.admin-state {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border: 1px solid currentcolor;
    border-radius: 999px;
    font-size: 0.8125rem;
}

.admin-state--published {
    color: #2f6b3a;
}

.admin-state--draft {
    color: var(--ink-soft);
}

.admin-state--scheduled {
    color: var(--sapele);
}

.admin-state--archived {
    color: #a3231b;
}

/* --------------------------------------------------- media library */

.admin-upload {
    max-width: 42rem;
    margin-bottom: 2.5rem;
    padding: 1rem 1.1rem;
    border: 1px solid var(--rule);
    border-radius: 3px;
    background: var(--maple-deep);
}

.admin-media-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 1.5rem;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
    align-items: start;
}

.admin-media-item figure {
    margin: 0;
}

.admin-media-item img {
    display: block;
    width: 100%;
    height: auto;
    background: var(--maple-deep);
    border: 1px solid var(--rule);
    border-radius: 2px;
}

.admin-media-item figcaption {
    padding-top: 0.4rem;
    font-size: 0.875rem;
    word-break: break-word;
}

.admin-media-meta {
    display: block;
    color: var(--ink-soft);
}

/* ---------------------------------------------------------------- blazor error ui */

#blazor-error-ui {
    display: none;
    position: fixed;
    inset: auto 0 0 0;
    z-index: 1000;
    padding: 0.9rem 1.25rem;
    background: var(--epoxy);
    color: var(--maple);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    float: right;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

/* ---------------------------------------------------------------- the basket */

.cart {
    max-width: 46rem;
}

.cart-empty {
    padding: 1.25rem 0;
}

.cart-lines {
    list-style: none;
    margin: 0;
    padding: 0;
}

.cart-line {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 2rem;
    padding: 1.25rem 0;
    border-bottom: 1px solid var(--rule);
}

.cart-line__title {
    margin: 0 0 0.5rem;
    font-size: 1.125rem;
}

.cart-line__parts {
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.875rem;
    color: var(--ink-soft);
}

.cart-line__parts li {
    display: flex;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 0.15rem 0;
}

/*
    Tabular figures so the amounts form a readable column, and the same treatment as the designer's
    breakdown — a customer who checked the arithmetic there should not have to re-learn the layout
    here. The deposit receipt learned this the hard way: line items that rendered as labelled
    settings rather than as a bill.
*/
.cart-line__amount,
.cart-line__total {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.cart-line__money {
    text-align: right;
    flex-shrink: 0;
}

.cart-line__total {
    margin: 0 0 0.6rem;
    font-size: 1.125rem;
    font-weight: 700;
}

/*
    A link styled as a button, not a button. Removing is destructive and posts; continuing is
    navigation. Making them look identical would invite the wrong one to be pressed at the moment
    the customer is deciding to spend money.
*/
.cart-remove {
    background: none;
    border: 1px solid var(--rule);
    border-radius: 3px;
    padding: 0.3rem 0.7rem;
    font: inherit;
    font-size: 0.875rem;
    color: var(--ink-soft);
    cursor: pointer;
}

.cart-remove:hover {
    border-color: var(--ink-soft);
    color: var(--ink);
}

.cart-summary {
    padding-top: 1.25rem;
}

.cart-subtotal {
    display: flex;
    justify-content: space-between;
    gap: 1.5rem;
    margin: 0 0 0.75rem;
    font-size: 1.375rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.cart-note {
    margin: 0 0 1.25rem;
    font-size: 0.875rem;
    color: var(--ink-soft);
}

.cart-continue {
    display: inline-block;
    background: var(--epoxy);
    color: var(--maple);
    padding: 0.6rem 1.4rem;
    border-radius: 3px;
    text-decoration: none;
    font-weight: 700;
}

.cart-continue:hover {
    background: var(--ink);
}

@media (max-width: 40rem) {
    .cart-line {
        flex-direction: column;
        gap: 0.75rem;
    }

    .cart-line__money {
        text-align: left;
    }
}

/* ---------------------------------------------------------------- checkout
   The last page before an order exists. Deliberately plainer than the basket:
   there is nothing to browse here and every element that is not the total, the
   split, or the button is competing with them. */

.checkout {
    max-width: 46rem;
}

.checkout-empty {
    padding: 1.25rem 0;
}

.checkout-lines ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.checkout-line {
    display: flex;
    justify-content: space-between;
    gap: 2rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--rule);
}

.checkout-line span:last-child,
.checkout-total span:last-child {
    font-variant-numeric: tabular-nums;
}

.checkout-total {
    display: flex;
    justify-content: space-between;
    gap: 1.5rem;
    margin: 1rem 0 0;
    font-size: 1.375rem;
    font-weight: 700;
}

/* The two dollar amounts the customer is agreeing to. Given its own weight
   because ADR-0012 is explicit that a deposit model is only fair if the split
   is impossible to miss. */
.checkout-split {
    font-size: 1.125rem;
    font-weight: 700;
    margin: 0 0 0.75rem;
}

.checkout-lead-time,
.checkout-note {
    font-size: 0.875rem;
    color: var(--ink-soft);
}

/* A price rose. Warm rather than alarming - the customer has done nothing
   wrong, and nothing has been charged. */
.checkout-reprice {
    border: 2px solid var(--epoxy);
    border-radius: 3px;
    padding: 1rem 1.25rem;
    margin: 0 0 1.5rem;
}

.checkout-reprice__lines {
    list-style: none;
    margin: 0 0 1rem;
    padding: 0;
}

.checkout-reprice__lines li {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    padding: 0.5rem 0;
    font-variant-numeric: tabular-nums;
}

.checkout-reprice__delta {
    font-weight: 700;
}

.checkout-button {
    background: var(--maple);
    color: var(--ink);
    border: 2px solid var(--epoxy);
    padding: 0.6rem 1.4rem;
    border-radius: 3px;
    font: inherit;
    font-weight: 700;
    cursor: pointer;
}

.checkout-button--primary {
    background: var(--epoxy);
    color: var(--maple);
}

.checkout-button:hover {
    background: var(--ink);
    color: var(--maple);
}

.checkout-blocked {
    font-weight: 700;
}

/* The order exists. Bordered so the reference number is findable when somebody
   scrolls back to it a week later looking for what to quote in an email. */
.checkout-placed {
    border: 2px solid var(--epoxy);
    border-radius: 3px;
    padding: 1.25rem 1.5rem;
}

.checkout-reference strong {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    word-break: break-all;
}

@media (max-width: 40rem) {
    .checkout-line {
        flex-direction: column;
        gap: 0.25rem;
    }
}

/* ---------------------------------------------------------- admin: orders
   The screen Scott's checkout decision was made for: somewhere to read what a
   customer configured, before any wood is cut. */

.admin-table--compact th,
.admin-table--compact td {
    padding: 0.3rem 0.75rem 0.3rem 0;
    font-size: 0.875rem;
}

.admin-table__money {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Reserved for the two things on this screen that would be expensive to get
   wrong: an unpaid deposit, and a split that does not add up. Not used for
   ordinary information, so that it keeps meaning "stop and read this". */
.admin-warning {
    border-left: 4px solid var(--epoxy);
    padding: 0.6rem 0 0.6rem 0.9rem;
    margin: 1rem 0;
}

.admin-order-lines {
    list-style: none;
    margin: 0;
    padding: 0;
}

.admin-order-line {
    border-bottom: 1px solid var(--rule);
    padding: 1rem 0;
}

.admin-order-line h3 {
    margin: 0 0 0.5rem;
}

.admin-order-line__facts,
.admin-order-money {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.25rem 1rem;
    margin: 0 0 0.75rem;
    font-size: 0.875rem;
}

.admin-order-line__facts dt,
.admin-order-money dt {
    color: var(--ink-soft);
}

.admin-order-line__facts dd,
.admin-order-money dd {
    margin: 0;
}

.admin-order-money {
    font-size: 1rem;
}

.admin-order-money dd {
    font-variant-numeric: tabular-nums;
}

/* Checkout's two questions: how it gets there, and when they need it. */
.checkout-fieldset {
    border: none;
    padding: 0;
    margin: 1rem 0;
}

.checkout-fieldset legend {
    padding: 0;
    font-weight: 700;
}

.checkout-choice {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    margin: 0.5rem 0;
}

.checkout-choice input[type="radio"] {
    width: 1.5rem;
    height: 1.5rem;
    margin: 0;
    flex: 0 0 auto;
}

.checkout-date {
    font: inherit;
    padding: 0.4rem;
}

/* "Optional" has to be visible without shouting - a customer who reads it as
   required will invent a date they do not mean. */
.checkout-optional {
    font-weight: 400;
    font-size: 0.8125rem;
    color: var(--ink-soft);
}
