/* components.css -- Buttons, tool panel, forms, auth, example lists, code
   Part of the site stylesheet, split out of the former single
   site.css. Load order is significant and is fixed in
   src/view/layout.php -- theme first (tokens), then base, then
   layout, then components. Rules were moved verbatim, in their
   original order, so the cascade is unchanged. */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--button-height);
    padding: 0 var(--button-padding-lg);
    background: var(--bg-neutral-accent);
    color: var(--fg-inverse-accent);
    font-size: var(--button-font-size);
    font-weight: var(--button-font-weight);
    border: none;
    /* --brm doubles the radius in corner-shape-supporting browsers (see
       --brm's own definition) -- .nav-cta below resets both back to
       plain/round, since a pill shape (its own border-radius: 9999px)
       can't be doubled without breaking (see
       https://orgpad.info/blog/squircles' own "Pill shapes are not
       possible" section). */
    border-radius: calc(var(--button-border-radius) * var(--brm));
    corner-shape: var(--corner-shape);
    cursor: pointer;
    text-decoration: none;
}

.button:hover {
    background: var(--bg-neutral-accent-hover);
    color: var(--fg-inverse-accent);
    text-decoration: none;
}

.button-secondary {
    background: transparent;
    color: var(--fg-neutral-accent);
    border: 1px solid var(--border-neutral-default);
}

.button-secondary:hover {
    background: var(--bg-neutral-section);
    color: var(--fg-neutral-accent);
}

.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-3);
    align-items: center;
    margin: var(--spacing-5) 0;
}

.lead {
    font-size: var(--text-size-lead);
    color: var(--fg-neutral-body);
    text-wrap: balance;
}

.caption {
    font-size: var(--text-size-small);
    color: var(--fg-neutral-muted);
}

/* tool panel -- a boxed, app-like container for a live demo */

.tool-panel {
    border: 1px solid var(--border-neutral-default);
    border-radius: var(--rounded-xl);
    padding: var(--spacing-8) var(--spacing-6);
    margin: 0;
    background: var(--bg-raised);
    box-shadow: var(--shadow-sm);
}

.tool-panel-header {
    font-size: var(--text-size-small);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--fg-neutral-muted);
    margin: 0 0 var(--spacing-5);
    padding-bottom: var(--spacing-3);
    border-bottom: 1px solid var(--border-neutral-subtle);
}

/* tool-with-examples: the tool panel and its examples list are two
   INDEPENDENT elements side by side -- not two panes of one shared
   frame (that was the previous design, reverted: examples read as
   part of the tool's own border, when it should sit next to the tool
   instead). */
.tool-with-examples {
    display: grid;
    grid-template-columns: 1.618fr 1fr;
    gap: var(--spacing-6);
    align-items: start;
    margin: var(--spacing-6) 0;
}

.examples-panel {
    border-radius: var(--rounded-xl);
    padding: var(--spacing-6);
    background: var(--bg-raised);
}

@media (max-width: 640px) {
    .tool-with-examples {
        grid-template-columns: 1fr;
        gap: var(--spacing-6);
    }
}

/* demo form */

form.demo {
    margin: 0;
}

form.demo label {
    display: block;
    font-size: var(--label-font-size);
    font-weight: var(--label-font-weight);
    margin-bottom: var(--spacing-2);
}

form.demo input[type="text"] {
    width: 100%;
    height: var(--input-height);
    font-family: var(--font-mono);
    font-size: var(--input-font-size);
    padding: 0 var(--input-padding-md);
    border: 1px solid var(--border-input);
    border-radius: var(--input-border-radius);
    background: var(--bg-input);
    color: var(--body-color);
}

form.demo input[type="text"]:focus {
    outline: none;
    border-color: var(--border-input-focus);
}

form.demo .field-row {
    display: flex;
    gap: var(--spacing-4);
    align-items: flex-end;
}

form.demo .field-name {
    flex: 1;
    min-width: 0;
}

form.demo .field-country {
    width: 5.5em;
}

form.demo select.input-country {
    width: 100%;
    height: var(--input-height);
    font-family: var(--font-mono);
    font-size: var(--input-font-size);
    padding: 0 var(--input-padding-md);
    padding-right: calc(var(--input-padding-md) * 2 + 10px);
    border: 1px solid var(--border-input);
    border-radius: var(--input-border-radius);
    background-color: var(--bg-input);
    color: var(--body-color);
    /* Flat chevron instead of the browser's native (OS-specific,
       skeuomorphic on some platforms) dropdown arrow -- appearance:none
       strips that chrome entirely, so the arrow has to be painted back
       on manually via background-image. #808080 is hardcoded (a plain
       background-image can't reference a CSS custom property) but
       reads fine against both --bg-input values (near-white/near-black). */
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23808080' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--input-padding-md) center;
    /* .field-country's narrow fixed width clips the closed box down to
       roughly the leading "XX" code -- the dropdown list itself isn't
       width-constrained the same way, so it still shows the full
       "XX — Name" option text once opened. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

form.demo select.input-country:focus {
    outline: none;
    border-color: var(--border-input-focus);
}

.submit-row {
    /* margin-top lives here, not on the button itself -- a margin on
       just one flex item would grow its margin box and throw off
       align-items: center between the button and the spinner next to
       it (which has no margin of its own). */
    display: flex;
    align-items: center;
    gap: var(--spacing-3);
    margin: var(--spacing-3) 0 0;
}

.spinner {
    /* Hidden by default -- #tool's _tool.php script adds/relies on the
       swap() fetch to toggle #tool.loading, since a real network
       round-trip happens even though the form still degrades to a
       plain full-page GET without JS (no spinner needed in that case,
       the browser's own loading indicator covers it). */
    display: none;
    width: 18px;
    height: 18px;
    border: 2px solid var(--border-neutral-default);
    border-top-color: var(--fg-neutral-accent);
    border-radius: var(--rounded-full);
    animation: spinner-rotate 0.6s linear infinite;
}

#tool.loading .spinner {
    display: inline-block;
}

@keyframes spinner-rotate {
    to {
        transform: rotate(360deg);
    }
}

/* contact-layout: the /contact page itself -- no separate hero above
   the form, a direct two-column split (copy left, form right) instead,
   both living in the page's one .page-section. */

.contact-layout {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--spacing-12);
    align-items: start;
    width: 100%;
}

.contact-info h1 {
    max-width: none;
}

.checklist {
    list-style: none;
    padding: 0;
    margin: var(--spacing-6) 0 0;
    max-width: none;
}

.checklist li {
    display: flex;
    align-items: center;
    gap: var(--spacing-3);
    padding: var(--spacing-2) 0;
    color: var(--fg-neutral-body);
}

.checklist li::before {
    content: "\2713";
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    border-radius: var(--rounded-full);
    background: var(--bg-neutral-section);
    color: var(--fg-neutral-accent);
    font-size: var(--text-size-small);
}

.contact-form-label {
    font-weight: var(--weight-semibold);
    margin-bottom: var(--spacing-4);
}

@media (max-width: 780px) {
    .contact-layout {
        grid-template-columns: 1fr;
        gap: var(--spacing-8);
    }
}

/* contact-form/auth-form: the field stack itself, reusing form.demo's
   input look (mono font, same border/radius tokens) without its
   two-column .field-row layout, which is specific to the name+country
   pair on the demo tool. auth-form (register/login) shares every rule
   below rather than duplicating them. */

.contact-form,
.auth-form {
    max-width: 32em;
}

/* auth-layout: register/login/account -- a single narrow column
   (unlike .contact-layout's two-column split, there's no second
   column of copy to put next to these). */
.auth-layout {
    max-width: 32em;
}

.auth-layout h1 {
    margin-bottom: var(--spacing-3);
}

.auth-layout .lead {
    margin-bottom: var(--spacing-8);
}

.auth-layout .caption {
    margin-top: var(--spacing-6);
}

.field-decoy {
    /* Honeypot for Contact_controller::on_contact() -- off-screen via
       absolute positioning, not display:none/visibility:hidden, since
       those are the first things a scraper checks for when deciding
       which fields to skip. Real visitors never see or reach it
       (no tab stop, aria-hidden), so it should always arrive empty. */
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.contact-form .field,
.auth-form .field {
    margin-bottom: var(--spacing-5);
}

.contact-form label,
.auth-form label {
    display: block;
    font-size: var(--label-font-size);
    font-weight: var(--label-font-weight);
    margin-bottom: var(--spacing-2);
}

.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea,
.auth-form input[type="text"],
.auth-form input[type="email"],
.auth-form input[type="password"] {
    width: 100%;
    font-family: var(--font-mono);
    font-size: var(--input-font-size);
    padding: var(--input-padding-md);
    border: 1px solid var(--border-input);
    border-radius: var(--input-border-radius);
    background: var(--bg-input);
    color: var(--body-color);
}

.contact-form input[type="text"],
.contact-form input[type="email"],
.auth-form input[type="text"],
.auth-form input[type="email"],
.auth-form input[type="password"] {
    height: var(--input-height);
    padding: 0 var(--input-padding-md);
}

.contact-form textarea {
    resize: vertical;
}

.contact-form input:focus,
.contact-form textarea:focus,
.auth-form input:focus {
    outline: none;
    border-color: var(--border-input-focus);
}

.contact-form .field .warning,
.auth-form .field .warning {
    display: block;
    margin-top: var(--spacing-2);
    font-size: var(--text-size-label);
}

.examples-label {
    font-size: var(--text-size-label);
    font-weight: var(--weight-medium);
    color: var(--fg-neutral-body);
    margin-bottom: var(--spacing-2);
}

ul.examples {
    list-style: none;
    padding: 0;
    margin: 0;
    max-width: none;
}

ul.examples li {
    border-bottom: 1px solid var(--border-neutral-subtle);
}

ul.examples li:last-child {
    border-bottom: none;
}

ul.examples a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-3);
    padding: var(--spacing-2) 0;
    color: var(--fg-neutral-body);
    font-family: var(--font-mono);
    font-size: var(--text-size-detail);
    text-decoration: none;
}

ul.examples a .arrow {
    color: var(--fg-neutral-muted);
    flex-shrink: 0;
}

ul.examples a:hover {
    color: var(--fg-info-body);
}

ul.examples a:hover .arrow {
    color: var(--fg-info-body);
}

/* benefit-list: a "we help you" style benefit list (icon + one-line
   outcome), scannable in a way a full card grid isn't -- used for the
   "Use cases" section instead of another card-grid. */

ul.benefit-list {
    list-style: none;
    padding: 0;
    margin: 0;
    max-width: none;
}

ul.benefit-list li {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-3);
    padding: var(--spacing-3) 0;
    border-bottom: 1px solid var(--border-neutral-subtle);
    color: var(--fg-neutral-body);
}

ul.benefit-list li:last-child {
    border-bottom: none;
}

.benefit-icon {
    flex-shrink: 0;
}

/* did-you-mean: same "whole line is the click target, arrow on the
   right" affordance as ul.examples a, so re-clicking to adopt a
   suggestion reads the same way as picking an example. */
a.did-you-mean {
    display: flex;
    align-items: center;
    gap: var(--spacing-2);
    color: var(--fg-neutral-body);
    text-decoration: none;
}

a.did-you-mean .arrow {
    color: var(--fg-neutral-muted);
}

a.did-you-mean:hover,
a.did-you-mean:hover .arrow {
    color: var(--fg-info-body);
}

.warning {
    color: var(--fg-notice-body);
}

/* code */

pre {
    background: var(--bg-neutral-section);
    border: 1px solid var(--border-neutral-default);
    border-radius: var(--snippet-border-radius);
    padding: var(--spacing-4);
    overflow-x: auto;
    font-family: var(--font-mono);
    font-size: var(--text-size-detail);
    line-height: 1.5;
}

code {
    font-family: var(--font-mono);
}

/* parse result -- human-readable first, raw JSON tucked behind <details> */
