/* ---- Shared primitives ------------------------------------------------------------------------
   Small patterns both sites need. Everything here is opt-in by class name, so linking this file
   changes nothing until a screen asks for one.

   What belongs here: a pattern used by more than one screen, whose appearance should not be a
   per-screen decision. What does not: page layout, which stays with the page. */

/* ---- Screen-reader-only text -------------------------------------------------------------------
   Announced by assistive technology, never painted.

   ⚠ THIS WAS MISSING AND THE MARKUP USED IT ANYWAY (#38). ThemePicker asked for .visually-hidden,
   nothing defined it, and the browser does not complain about a class it has never heard of - so
   the label meant for a screen reader was simply drawn on the page beside the control. An
   undefined class is the quietest failure in this codebase: no build error, no test, no exception,
   just a page that is wrong in a way only a person looking at it can see.

   THE CLIP-RECT PATTERN, NOT display:none OR visibility:hidden. Those two remove the element from
   the accessibility tree as well as from the page, which would silence exactly the text this
   exists to announce - an icon-only control with no accessible name at all, which is worse than
   the visible label was.

   NOT BOOTSTRAP. The class name is Bootstrap's, because that is what the markup already said and
   what anybody writing more markup will reach for; pulling in a CSS framework to supply one
   utility is not a trade worth making. */

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---- Notices ---------------------------------------------------------------------------------
   One shape for "this failed", "careful", and "that worked".

   THE REASON THIS EXISTS: success messages were rendering through .upload-hint, which is amber
   #8a6d00, on five separate screens. Every completed save reported itself in warning color. A
   color that means both "done" and "be careful" means neither. */

.carvin-notice {
    display: flex;
    gap: var(--cv-space-2);
    margin: var(--cv-space-3) 0;
    padding: var(--cv-space-2) var(--cv-space-3);
    border: 1px solid transparent;
    border-radius: var(--cv-radius-md);
    font-size: var(--cv-text-base);
    line-height: var(--cv-leading);
}

.carvin-notice ul {
    margin: 0;
    padding-left: 1.15rem;
}

.carvin-notice li + li {
    margin-top: var(--cv-space-1);
}

.carvin-notice--success {
    border-color: color-mix(in srgb, var(--cv-success-text) 35%, transparent);
    background: var(--cv-success-bg);
    color: var(--cv-success-text);
}

.carvin-notice--warning {
    border-color: color-mix(in srgb, var(--cv-warning-text) 35%, transparent);
    background: var(--cv-warning-bg);
    color: var(--cv-warning-text);
}

.carvin-notice--error {
    border-color: color-mix(in srgb, var(--cv-danger-text) 35%, transparent);
    background: var(--cv-danger-bg);
    color: var(--cv-danger-text);
}

/* ---- Status badges ---------------------------------------------------------------------------
   Compact semantic state, in business language.

   Screens were reaching for .scope-tenant / .scope-company / .scope-branch to color statuses.
   Those classes mean "which level this configuration value came from" - a genuinely different
   idea, and one whose colors are load-bearing on the settings screens. Borrowing them made a
   packet's approval state look like a scope. */

.carvin-badge {
    display: inline-flex;
    align-items: center;
    padding: 0 var(--cv-space-2);
    min-height: 1.15rem;
    border: 1px solid transparent;
    border-radius: var(--cv-radius-sm);
    font-size: var(--cv-text-xs);
    font-weight: var(--cv-weight-semibold);
    line-height: 1.15rem;
    white-space: nowrap;
}

.carvin-badge--neutral {
    border-color: var(--cv-border);
    background: var(--cv-surface-subtle);
    color: var(--cv-text-soft);
}

.carvin-badge--info {
    border-color: color-mix(in srgb, var(--cv-accent) 40%, transparent);
    background: color-mix(in srgb, var(--cv-accent) 12%, var(--cv-surface));
    color: var(--cv-accent-strong);
}

.carvin-badge--success {
    border-color: color-mix(in srgb, var(--cv-success-text) 40%, transparent);
    background: var(--cv-success-bg);
    color: var(--cv-success-text);
}

.carvin-badge--warning {
    border-color: color-mix(in srgb, var(--cv-warning-text) 40%, transparent);
    background: var(--cv-warning-bg);
    color: var(--cv-warning-text);
}

.carvin-badge--danger {
    border-color: color-mix(in srgb, var(--cv-danger-text) 40%, transparent);
    background: var(--cv-danger-bg);
    color: var(--cv-danger-text);
}

/* ---- Form field layout -----------------------------------------------------------------------
   A group of .carvin-field, in columns that collapse rather than overflow. Replaces the popup-only
   .edit-form / .edit-group pair, which a page-level form had already started borrowing. */

.carvin-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: var(--cv-space-3) var(--cv-space-4);
}

.carvin-fields--wide {
    grid-column: 1 / -1;
}

/* A row AFTER a group of fields, rather than in it - the button under the fields, on eighteen screens.
   Outside the grid the span above means nothing, so the button sat flush against the last box. Carvin,
   2026-10-13, on Assign packet: "Fix spacing between drop down and button." */
.carvin-fields + .carvin-fields--wide {
    margin-top: var(--cv-space-4);
}

/* One column, whatever the width. The auto-fit grid above is right for a form that is the whole
   page; it is wrong inside a narrow editor column, where it would fit two 15rem fields side by
   side and reintroduce exactly the ragged rows .carvin-editor-split exists to get rid of. */
.carvin-fields--stacked {
    grid-template-columns: minmax(0, 1fr);
}

/* ---- An editor beside the list it edits --------------------------------------------------------
   Carvin, 2026-10-10, on the Skills screen: "This looks sloppy and very unprofessional. Put the
   data entry on the left and grid of the skills on the right. Data entry should be stacked
   vertically."

   ⚠ WHAT WAS ACTUALLY WRONG. The add form was four .carvin-field across the full page width, each
   with help text of a different length, so the four captions ended at four different depths and
   the Add button sat alone under the tallest one. Below that, separated by the full height of all
   that, was the list the form adds to. Nothing was unstyled - the auto-fit grid simply models a
   form that IS the page, and here the form is one half of a working screen.

   A FIXED LEFT COLUMN, NOT A FRACTION OF THE PAGE. An input for a short code does not get better
   at 40% of a 2560px monitor, and the list is the part that wants the room - it grows a row every
   time somebody uses the form beside it.

   minmax(0, 1fr) ON THE RIGHT, not 1fr: a grid item's default min-width is auto, so a wide table
   pushes the column past its share instead of scrolling, and the left column gets squeezed into
   nothing. This is the whole reason the right-hand side of a split like this misbehaves. */

.carvin-editor-split {
    display: grid;
    grid-template-columns: minmax(18rem, 24rem) minmax(0, 1fr);
    gap: var(--cv-space-4);
    align-items: start;
}

/* Stacked below a laptop width. Two columns at 900px gives a cramped form beside a cramped table,
   which is worse than either at full width. */
@media (max-width: 62rem) {
    .carvin-editor-split {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Both halves may shrink. Without this the table's intrinsic width wins and the layout overflows
   the page rather than the table scrolling inside its own column. */
.carvin-editor-split > * {
    min-width: 0;
}

/* ---- Filter rows -------------------------------------------------------------------------------
   A row of controls that NARROWS a list, which is a different thing from a form that EDITS a record
   - and the difference is why .carvin-fields looked wrong wherever a filter row borrowed it.

   Carvin, 2026-09-01, comparing Find an applicant with the compliance log: "I really don't like the
   look of this search interface especially compared to how elegant the design looks on the
   compliance search section."

   ⚠ THE DIAGNOSIS WAS THE OPPOSITE OF WHAT IT LOOKED LIKE. Find an applicant was not unstyled; it
   used .carvin-fields, the house pattern behind nineteen files. The compliance log was the one-off,
   a single .compliance-filters rule in one host's stylesheet. What was actually wrong is that the
   house pattern models an EDIT FORM and only that:

     .carvin-fields   grid, minmax(15rem) columns, labels UPPERCASE and tracked, inputs stretched
     a filter row     flex, controls sized to their content, labels in sentence case, button inline

   That is where "APPLICANT CODE OR NAME" in small caps above a 700px box for an eight-character code
   came from. Nobody chose it for that screen; it is correct for an edit form and wrong here.

   SO THE ONE-OFF WAS PROMOTED RATHER THAN THE PATTERN CHANGED. .carvin-fields is untouched - it is
   right for what it models and nineteen files depend on it. This is its sibling.

   NOT NAMED .compliance-filters. That name is a lie on the applicants screen, the same reasoning
   that gave .panel its own name rather than reusing .data-right: a class named for the one screen
   it started on is a class the next screen has to apologise for. */

/* ⚠ A GRID WITH SHARED ROWS, NOT A FLEX ROW. Carvin, 2026-09-01: "This screen still does not look
   good can you at least align the input boxes."

   The first attempt used flex with align-items: flex-end, which aligns the BOTTOM OF EACH FIELD -
   label, control and help text together. A field carrying help text is therefore taller, so its
   control floats up by exactly the height of that text, and two inputs on one row sit at two
   different heights. It looked like carelessness and was a wrong rule.

   Three named rows fix it by construction: every label goes on row 1, every control on row 2, every
   caption on row 3, whatever any individual field carries. subgrid is what lets each label keep its
   own element while its parts land in the shared rows. */

.carvin-filters {
    display: grid;

    /* Columns sized to their content, wrapping when the row runs out. The compliance log puts four
       controls here and a narrow window has to fold rather than overflow. */
    grid-template-columns: repeat(auto-fit, minmax(12rem, max-content));
    grid-template-rows: auto auto auto;
    align-items: start;
    gap: 0 var(--cv-space-3);
    margin: var(--cv-space-3) 0 var(--cv-space-4);
}

/* Each field spans all three rows and inherits them, so its label, control and caption sit on the
   same lines as every other field's. */
.carvin-filters > label {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / 4;
    gap: var(--cv-space-1);

    font-size: var(--cv-text-sm);
    color: var(--cv-text-muted);

    /* ⚠ SENTENCE CASE, and this is the line that answered the original complaint.
       .carvin-field > span sets text-transform: uppercase, which is what shouted
       APPLICANT CODE OR NAME across the screen. */
    text-transform: none;
    letter-spacing: normal;
}

/* The button belongs on the CONTROL row, beside the inputs rather than below the tallest field. */
.carvin-filters > button {
    grid-row: 2;
    align-self: stretch;
}

/* Sized to what goes in them rather than to the column. An applicant code is eight characters and a
   date is ten; stretching either is what made the search box look like a comment field. */
.carvin-filters input:not([type="checkbox"]):not([type="radio"]),
.carvin-filters select {
    width: 100%;
    min-width: 0;
}

/* The caption under a control. On row 3, so a field that has one does not shift its neighbours. */
.carvin-filters small {
    color: var(--cv-text-muted);
    font-size: var(--cv-text-xs);
}

.carvin-fieldset {
    min-width: 0;
    border: 0;
    margin: 0;
    padding: 0;
}

.carvin-fieldset > legend {
    padding: 0;
    margin-bottom: var(--cv-space-2);
    color: var(--cv-text-muted);
    font-size: var(--cv-text-sm);
    font-weight: var(--cv-weight-semibold);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* ---- The main action on a page -----------------------------------------------------------------
   ⚠ EIGHT BUTTONS CARRIED THIS CLASS AND NOTHING DEFINED IT (#47), including "Sign in" and the
   applicant's "Submit". They rendered as browser-default buttons, identical to Cancel beside them -
   so the one control a page wants you to press looked exactly like the one it does not. Nothing
   failed; there was simply no rule.

   SHARED RATHER THAN THREE COPIES: all three hosts use it, and three copies is three chances for
   the primary action to look different depending on which screen you are on. */

.primary {
    background: var(--cv-accent);
    color: var(--cv-accent-contrast);
    border: 1px solid var(--cv-accent);
    border-radius: var(--cv-radius-sm);
    padding: 0.4rem 1rem;
    font-weight: var(--cv-weight-semibold);
    cursor: pointer;
}

.primary:hover:not(:disabled) {
    background: var(--cv-accent-strong);
    border-color: var(--cv-accent-strong);
}

.primary:disabled {
    /* Visibly unavailable rather than merely unresponsive. A disabled button that looks pressable
       gets pressed repeatedly, which reads as the page being broken. */
    opacity: 0.55;
    cursor: not-allowed;
}

/* ---- Recovering from a dropped circuit ----------------------------------------------------------
   The link in the reconnect banner on all three hosts. Undefined until #47, so the one way out of a
   dead page was an unstyled link inside a modal. */

.reload {
    color: var(--cv-accent);
    font-weight: var(--cv-weight-medium);
    text-decoration: underline;
}

/* ---- A button that reads as a link --------------------------------------------------------------
   An action that undoes or reveals something, where a full button would overstate it: "Clear and
   start again" under a signature, "Show the code", "Use a different address".

   ⚠ DEFINED ONCE, IN TENANTADMIN, AND NAMED BY FORTY-ODD PLACES ACROSS BOTH SITES (#64). Five Portal
   pages and the shared SignaturePad asked for it and the Portal never links TenantAdmin's app.css,
   so the control that undoes a signature rendered as a default grey browser button for every
   applicant. Nothing failed: an undefined class is not an error, and the coverage test pooled every
   stylesheet in the repository into one set, so it could not see that the rule was in a file the
   Portal does not serve.

   The color is --cv-accent since #227, where Staffily navy became the link color. It used to be
   #0969da, the blue TenantAdmin had always used, kept when the rule moved so that moving it and
   restyling forty controls stayed two changes. The brand was that second, deliberate change - and
   the token also gives dark mode a link it can read. */

.link-button {
    background: none;
    border: none;
    color: var(--cv-accent);
    cursor: pointer;
    padding: 0;
    font-size: 0.9rem;
    text-decoration: underline;
}

/* ---- A checkbox and its label, on one line ------------------------------------------------------
   ⚠ THE SAME SHAPE AS .link-button, AND FOUND THE SAME WAY. Twenty-odd uses in TenantAdmin and three
   in the Portal - Register, SkillsStep and WorkAuthorization - with the only definition in
   TenantAdmin's app.css. So the applicant's "I am a citizen" and "contact me about this job" rows
   fell back to the browser default while the admin's did not.

   TenantAdmin held TWO conflicting definitions of this class, one at line 358 and one at line 538.
   Same specificity, so the later one won everywhere and the earlier one had never applied to
   anything. This is the one that was in effect; the dead one is gone. */

.checkbox-label {
    display: inline-flex;
    gap: 0.35rem;
    align-items: baseline;
    font-size: 0.9rem;
}

/* ---- A list of forms, one per row ---------------------------------------------------------------
   An applicant reads it as "what is left to do" in MyForms; a recruiter reads it as "what they
   claimed" in ApplicantDetails. Same list, same separators.

   Defined only in the Portal until #64, and used by TenantAdmin's applicant detail page - the mirror
   image of .link-button above, and the reason this test now resolves per host rather than pooling.
   var(--cv-border) rather than the Portal's --carvin-line, which is an alias for it. */

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

.form-list li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.4rem 0;
    border-top: 1px solid var(--cv-border);
}

.form-list li:first-child {
    border-top: none;
}

/* ---- The privacy notice, and its preview --------------------------------------------------------
   A page or two of text an applicant has to be able to skim before agreeing. Bounded height so the
   Agree control stays reachable without scrolling past the whole notice, and scrollable so nothing
   is hidden - a notice you cannot finish reading is not one somebody can meaningfully agree to.

   ⚠ TENANTADMIN'S COPY SAID IT MIRRORED THE PORTAL AND DID NOT (#64): 70ch against 60ch, with
   different margins and a shorter scroll box. An administrator approved wording against a paragraph
   layout the applicant would never get, on a preview explicitly sold as "what the applicant sees".

   THE PORTAL'S NUMBERS WIN, because the Portal is where the text is actually read. FormattedPolicy
   renders both, so it takes its rules from here - the same arrangement as Notice above. */

.policy-scroll {
    max-height: 22rem;
    overflow-y: auto;
    background: var(--cv-surface);
    border: 1px solid var(--cv-border);
    border-radius: 0.5rem;
    padding: 1.25rem 1.5rem;
    margin-bottom: 1.25rem;
}

/* Visible focus, because tabindex="0" makes this a stop on the keyboard path and an outline is the
   only thing telling somebody the arrow keys will now scroll it. */
.policy-scroll:focus-visible {
    outline: 3px solid var(--cv-accent);
    outline-offset: 2px;
}

.policy-text h3 {
    font-size: 1.05rem;
    margin: 1.5rem 0 0.5rem;
}

.policy-text h3:first-child {
    margin-top: 0;
}

.policy-text p {
    margin: 0 0 0.75rem;
    max-width: 60ch;
}

/* ---- Error text ---------------------------------------------------------------------------------
   ⚠ A BOOTSTRAP NAME ON A PRODUCT THAT LOADS NO BOOTSTRAP. It arrived with the stock error page and
   was never defined, so the error heading rendered in ordinary body colour - the one page where the
   colour is carrying the message. Defined here rather than renamed: the class is in three hosts'
   error pages, which are framework-generated and will be regenerated with this name again. */

.text-danger {
    color: var(--cv-danger-text);
}

/* ---- Tabs ---------------------------------------------------------------------------------------
   ONE SCREEN THAT ANSWERS FOUR QUESTIONS, not four screens' worth of grid stacked vertically.
   Carvin, 2026-08-31, on the compliance log: "this would be better as tabs instead of stacking the
   grids on top of each other. That's just really bad design that can confuse the user." He was
   right, and the reason is specific: every one of those grids has its own search box, its own pager
   and its own column headers, so scrolling past one to reach the next means passing three controls
   that look like the ones you just used and are not.

   NOT .page-tab, WHICH ALREADY EXISTS AND IS NOT THIS. That one is the page selector above the
   template designer's document preview; "page" there means a page of a PDF. Reusing it would make
   its name a lie on this screen - the same reasoning that gave .panel its own name rather than
   reusing .data-right.

   HERE RATHER THAN IN A HOST STYLESHEET because both hosts link this file and neither has a tab
   strip yet. A pattern copied into the second host is a pattern that stops agreeing with the first.

   The strip scrolls rather than wrapping: a tab that reflows onto a second line moves when the set
   changes, and these are permission-dependent, so different people see different numbers of them. */
.tabstrip {
    display: flex;
    gap: 0.25rem;
    margin: 0 0 1rem;
    padding: 0;
    border-bottom: 1px solid var(--cv-border);
    overflow-x: auto;
}

.tabstrip__tab {
    padding: 0.5rem 1rem;
    text-decoration: none;
    border: 1px solid transparent;
    border-bottom: none;
    background: none;
    color: var(--cv-text-muted);
    cursor: pointer;
    white-space: nowrap;
    font: inherit;

    /* Sits ON the strip's border rather than above it, so the selected tab can erase its own
       segment and read as joined to the panel below. */
    margin-bottom: -1px;
}

/* Narrower tabs on a phone, so four of them fit across rather than the last one scrolling out of sight. */
@media (max-width: 40rem) {
    .tabstrip__tab {
        padding: 0.5rem 0.6rem;
    }
}

.tabstrip__tab:hover {
    color: var(--cv-text);
}

/* THE SELECTED TAB ERASES THE LINE UNDER ITSELF. A tint alone is not enough on a screen where the
   panel below is also a light surface - the join is what says which tab the content belongs to. */
.tabstrip__tab--active {
    background: var(--cv-surface);
    border-color: var(--cv-border);
    border-bottom: 1px solid var(--cv-surface);
    color: var(--cv-text);
    font-weight: 600;
}

/* HOW MANY ON THE TAB (Carvin, 2026-10-13), a small pill after the name. None for nothing: an empty tab
   says so by having no number. */
.tab-count {
    display: inline-block;
    min-width: 1.25rem;
    margin-left: 0.4rem;
    padding: 0 0.4rem;
    border-radius: 999px;
    background: var(--cv-surface-hover);
    border: 1px solid var(--cv-border);
    color: var(--cv-text-muted);
    font-size: 0.8em;
    font-weight: 600;
    line-height: 1.5;
    text-align: center;
}

.tabstrip__tab--active .tab-count {
    background: var(--cv-accent);
    border-color: var(--cv-accent);
    color: var(--cv-accent-contrast);
}

/* Keyboard users land here via the roving tabindex, and the outline is the only thing that says so. */
.tabstrip__tab:focus-visible {
    outline: 2px solid var(--cv-accent);
    outline-offset: -2px;
}

/* ---- The actions stacked in a grid row ----------------------------------------------------------
   Carvin, 2026-09-02: "I would like the actions to be in the 1st column. Also fix the styling as
   some are larger than others."

   ⚠ THE SIZES COULD NEVER HAVE AGREED BY ACCIDENT. A row's actions are a mix of anchors, which
   navigate to a page that gates itself, and buttons, which act here and are shown per permission.
   .link-button pins font-size: 0.9rem; a bare <a> inherits whatever the grid cell sets. Two numbers
   with nothing holding them together, and one of them belonging to DevExpress.

   SO THE CONTAINER DECIDES AND font: inherit CARRIES THE CELL'S OWN FONT to both kinds. There is no
   size in this rule to keep in step with anything.

   ⚠ NOT FOLDED INTO .link-button, which is right where it is used - beside body text, at 0.9rem,
   twenty-odd times across both hosts. This is the narrower case of a stack of them inside a cell.

   Replaces a column of <br /> tags. A flex column is what was meant, and it is what lets the gap be
   stated once rather than being whatever a line break happens to give. */

.grid-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
}

.grid-actions > a,
.grid-actions > button {
    font: inherit;
    color: var(--cv-accent);
    text-decoration: underline;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    text-align: left;
}

.grid-actions > button:disabled {
    color: var(--cv-text-muted);
    cursor: default;
}

/* ---- Powered by Staffily ------------------------------------------------------------------------
   On every page of all three sites, with the Staffily logo (#227; first added 2026-10-12 as "Powered
   by Carvin Software"). Small, quiet and last: the page belongs to the agency; this says whose
   software it runs on. */

.powered-by {
    padding: var(--cv-space-5) var(--cv-space-4) var(--cv-space-6);
    color: var(--cv-text-muted);
    font-size: var(--cv-text-xs);
    text-align: center;
}

.powered-by a {
    display: inline-flex;
    align-items: center;
    gap: var(--cv-space-2);
    color: inherit;
    text-decoration: none;
}

.powered-by a:hover {
    color: var(--cv-accent);
    text-decoration: underline;
}

/* The wordmark's cap height sits level with the 11px words beside it. */
.powered-by__logo {
    display: block;
    width: auto;
    height: 16px;
}

/* ---- The Staffily logo, one image per scheme (#227) ---------------------------------------------
   logo.svg is a navy shield for a light ground; logo-reversed.svg is a white shield for a dark one.
   The wordmark is orange in both. A component renders both and the scheme attribute the host stamps
   on <html> hides one - the shared UI may not ask which theme is running (FRAMEWORK.md §3.3), and an
   attribute is the whole interface. display:none, so assistive technology reads the logo once.

   ⚠ :root IN EVERY SELECTOR, for weight. A host's app.css loads after this file and gives its
   logo class display:block; at equal weight that later rule would win and show both images. */

:root .staffily-logo--dark {
    display: none;
}

:root[data-carvin-scheme="dark"] .staffily-logo--light {
    display: none;
}

:root[data-carvin-scheme="dark"] .staffily-logo--dark {
    display: block;
}

/* ---- The address check (#247) -------------------------------------------------------------------
   An entry and PostGrid's suggestion SIDE BY SIDE, which is what the issue asks for and what makes
   the difference readable at a glance. Shared because the applicant's registration, their details
   page and the staff applicant record all show the same choice, and three copies would drift.

   Stacked on a phone, where two columns of an address would wrap every line; the entry comes first
   either way, because it is theirs. The suggestion carries the accent border - it is the action the
   page leads with - and the bold parts inside it are what it changes. */

.address-choice {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    margin: 1rem 0 1.5rem;
}

@media (min-width: 40rem) {
    .address-choice {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.address-choice__option {
    border: 1px solid var(--cv-border);
    border-radius: 0.5rem;
    padding: 1rem 1.25rem;
}

.address-choice__option--suggested {
    border-color: var(--cv-accent);
    border-width: 2px;
}

.address-choice__heading {
    margin: 0 0 0.5rem;
    font-size: 0.95rem;
    color: var(--cv-text-muted);
}

.address-choice__lines {
    font-style: normal;
    line-height: 1.5;
    overflow-wrap: anywhere;
}

.address-choice__hint {
    margin: 0.75rem 0 0;
    font-size: 0.85rem;
    color: var(--cv-text-muted);
}
