/* ==========================================================================
 * WattWisely — components
 * ========================================================================== */

@layer components {

  /* -- Buttons ------------------------------------------------------------ */

  .btn {
    display: inline-flex;
    align-items: center;
    gap: var(--ww-space-2);
    padding: var(--ww-space-3) var(--ww-space-6);
    border: 1.5px solid transparent;
    border-radius: var(--ww-radius-full);
    font-size: var(--ww-step-0);
    font-weight: var(--ww-weight-semibold);
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--ww-motion-base) var(--ww-motion-ease),
                border-color var(--ww-motion-base) var(--ww-motion-ease),
                color var(--ww-motion-base) var(--ww-motion-ease),
                transform var(--ww-motion-fast) var(--ww-motion-ease);
  }

  .btn:active { transform: translateY(1px); }

  .btn--primary {
    background: var(--ww-primary);
    color: var(--ww-white);
  }

  .btn--primary:hover {
    background: var(--ww-primary-hover);
    color: var(--ww-white);
  }

  .btn--secondary {
    background: transparent;
    border-color: var(--ww-ink);
    color: var(--ww-ink);
  }

  .btn--secondary:hover {
    background: var(--ww-ink);
    color: var(--ww-white);
  }

  /* Green is a value signal, not a general button colour — reserved for a
     single page-level CTA. Ink label, never white (white on green is 2.5:1). */
  .btn--accent {
    background: var(--ww-accent);
    color: var(--ww-ink);
  }

  .btn--accent:hover {
    background: var(--ww-green-300);
    color: var(--ww-ink);
  }

  .btn--lg { padding: var(--ww-space-4) var(--ww-space-7); font-size: var(--ww-step-1); }

  /* On ink sections the secondary outline flips. */
  .section--ink .btn--secondary,
  .site-footer .btn--secondary {
    border-color: color-mix(in srgb, var(--ww-white) 40%, transparent);
    color: var(--ww-white);
  }

  .section--ink .btn--secondary:hover,
  .site-footer .btn--secondary:hover {
    background: var(--ww-white);
    color: var(--ww-ink);
  }

  /* -- Text link with arrow ----------------------------------------------- */

  .link-arrow {
    display: inline-flex;
    align-items: center;
    gap: var(--ww-space-2);
    font-weight: var(--ww-weight-semibold);
    text-decoration: none;
  }

  .link-arrow::after {
    content: "→";
    transition: transform var(--ww-motion-base) var(--ww-motion-ease);
  }

  .link-arrow:hover::after { transform: translateX(3px); }

  /* These are standalone CTAs, not links inside a sentence, so the target-size
     inline exception doesn't apply. Give them a full 44px on touch devices. */
  @media (pointer: coarse) {
    .link-arrow { min-height: 44px; }
  }

  /* -- Breadcrumb --------------------------------------------------------- */
  /* Rendered inside the hero on nested pages — /use-case/* now, /legal/* next.
     The separator is a ::before on the list item rather than a character in the
     markup, so a screen reader announces "Home, Use cases, Fleet" instead of
     reading a slash between every step. */

  .breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 var(--ww-space-3);
    margin: 0;
    padding: 0;
    max-width: none;
    list-style: none;
    font-size: var(--ww-step--1);
  }

  .breadcrumb li { margin-top: 0; }

  .breadcrumb li + li::before {
    content: "";
    display: inline-block;
    width: 0.35em;
    height: 0.35em;
    margin-inline-end: var(--ww-space-3);
    border-top: 1.5px solid var(--ww-muted);
    border-right: 1.5px solid var(--ww-muted);
    transform: rotate(45deg);
  }

  /* These are standalone links in a nav, not links inside a sentence, so the
     inline exception to WCAG 2.5.8 does not cover them. 24px of height plus the
     gap either side clears the 24×24 minimum without turning the trail into a
     tall bar on a phone. */
  .breadcrumb a {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    color: var(--ww-muted);
    text-decoration: none;
  }

  .breadcrumb a:hover { color: var(--ww-primary); text-decoration: underline; }

  .breadcrumb [aria-current] {
    color: var(--ww-ink);
    font-weight: var(--ww-weight-semibold);
  }

  .section--ink .breadcrumb a { color: color-mix(in srgb, var(--ww-white) 70%, transparent); }
  .section--ink .breadcrumb a:hover { color: var(--ww-white); }
  .section--ink .breadcrumb [aria-current] { color: var(--ww-white); }

  /* -- Card --------------------------------------------------------------- */

  .card {
    display: flex;
    flex-direction: column;
    gap: var(--ww-space-3);
    padding: var(--ww-space-6);
    background: var(--ww-white);
    border: 1px solid var(--ww-border);
    border-radius: var(--ww-radius-lg);
  }

  .card h3 { font-size: var(--ww-step-1); }

  .card p { font-size: var(--ww-step-0); margin: 0; }

  .card__icon {
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--ww-radius-md);
    background: var(--ww-teal-50);
    color: var(--ww-primary);
  }

  .card--link { text-decoration: none; color: inherit; transition: border-color var(--ww-motion-base) var(--ww-motion-ease), box-shadow var(--ww-motion-base) var(--ww-motion-ease), transform var(--ww-motion-base) var(--ww-motion-ease); }

  .card--link:hover {
    border-color: var(--ww-teal-300);
    box-shadow: var(--ww-shadow-md);
    transform: translateY(-2px);
    color: inherit;
  }

  .card--link .card__title { color: var(--ww-ink); }

  /* Optional checklist inside a card, and the link pinned to the foot so a
     row of cards with uneven copy still ends its links on one line. */
  .card__points li { font-size: var(--ww-step--1); }

  .card .link-arrow { margin-top: auto; }

  /* A callout centred under a feature grid or a steps list — the one note
     the section needs. */
  .feature-grid__note,
  .steps__note {
    max-width: 46rem;
    margin: var(--ww-space-8) auto 0;
  }

  /* Cards inside ink sections. */
  .section--ink .card {
    background: var(--ww-ink-soft);
    border-color: color-mix(in srgb, var(--ww-white) 12%, transparent);
  }

  .section--ink .card__icon {
    background: color-mix(in srgb, var(--ww-teal-300) 16%, transparent);
    color: var(--ww-teal-300);
  }

  .section--ink .card--link:hover { border-color: var(--ww-teal-400); }

  /* Link cards pin their title to ink for light sections; on ink it must flip. */
  .section--ink .card--link .card__title { color: var(--ww-white); }

  /* -- Stat --------------------------------------------------------------- */

  .stat__value {
    display: block;
    font-size: var(--ww-step-5);
    font-weight: var(--ww-weight-bold);
    line-height: 1;
    letter-spacing: -0.03em;
    color: var(--ww-ink);
  }

  .stat__label {
    display: block;
    margin-top: var(--ww-space-2);
    font-size: var(--ww-step--1);
    color: var(--ww-muted);
  }

  .section--ink .stat__value { color: var(--ww-accent); }
  .section--ink .stat__label { color: color-mix(in srgb, var(--ww-white) 70%, transparent); }

  /* -- Hero --------------------------------------------------------------- */
  /* Shared by every page using the hero component. A page sheet overrides
     these from the `pages` layer when it needs a different rhythm. */

  .hero { padding-block: clamp(2.5rem, 6vw, 4.5rem) var(--ww-section-y); }

  .hero__lead {
    font-size: var(--ww-step-1);
    max-width: 36rem;
  }

  .hero__note {
    font-size: var(--ww-step--1);
    color: var(--ww-muted);
    max-width: 36rem;
  }

  .section--ink .hero__note { color: color-mix(in srgb, var(--ww-white) 65%, transparent); }

  .hero__media { align-self: center; }

  /* Fan: two or three screens cascading right to left. The screen marked
     is-front sits at the right; is-mid and is-back step left by --fan-step
     and up by --fan-rise, so a strip of every screen stays visible. The
     offsets are transforms, as percentages of a screen's own box, so fan.js
     can rotate the classes and the screens glide to their new places. */
  .hero__fan {
    --fan-step: 14%;
    --fan-rise: 13.5%;
    --fan-ease: 700ms cubic-bezier(0.4, 0, 0.2, 1);
    position: relative;
    aspect-ratio: 16 / 9;
    width: 100%;
  }

  .hero__fan-item {
    position: absolute;
    width: 78%;
    right: 0;
    bottom: 0;
    background: var(--ww-white);
    border: 1px solid var(--ww-border);
    transition: transform var(--fan-ease), box-shadow var(--fan-ease);
  }

  .hero__fan-item.is-front { z-index: 3; transform: translate(0, 0); }

  .hero__fan-item.is-mid {
    z-index: 2;
    transform: translate(calc(-1 * var(--fan-step)), calc(-1 * var(--fan-rise)));
    box-shadow: var(--ww-shadow-md);
  }

  .hero__fan-item.is-back {
    z-index: 1;
    transform: translate(calc(-2 * var(--fan-step)), calc(-2 * var(--fan-rise)));
    box-shadow: var(--ww-shadow-sm);
  }

  @media (prefers-reduced-motion: reduce) {
    .hero__fan-item { transition: none; }
  }

  .hero__fan-item img,
  .hero__fan-item .ww-placeholder { width: 100%; height: auto; display: block; }

  /* A cut-out on transparency (a phone mockup) carries its own shadow and
     shape, so it gets no frame, and it is a third of the fan wide rather than
     most of it — a portrait phone at the full width would tower over the box. */
  .hero__fan-item--flat {
    width: 30%;
    background: transparent;
    border: 0;
    border-radius: 0;
    overflow: visible;
    box-shadow: none;
  }

  @media (min-width: 1024px) {
    .hero__split { align-items: center; }
  }

  /* -- Steps -------------------------------------------------------------- */

  .steps {
    list-style: none;
    padding: 0;
  }

  .steps > li { margin-top: 0; }

  /* The diagram above the steps: full container width, breathing room below. */
  .steps__media { margin-bottom: var(--ww-space-9); }

  /* Side layout: steps stacked in the narrow column, diagram in the wide one. */
  .steps--column {
    display: grid;
    gap: var(--ww-space-6);
    margin: 0;
  }

  .steps__side .steps__media { margin-bottom: 0; }

  /* The diagram needs the width more than the steps do. */
  @media (min-width: 1024px) {
    .steps__side { grid-template-columns: 4fr 8fr; }
  }

  .steps__media img,
  .steps__media .ww-placeholder { width: 100%; height: auto; }

  .steps h3 { font-size: var(--ww-step-1); }

  .step__number {
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--ww-radius-full);
    background: var(--ww-primary);
    color: var(--ww-white);
    font-weight: var(--ww-weight-bold);
    font-size: var(--ww-step-0);
  }

  /* -- FAQ ---------------------------------------------------------------- */
  /* <details>/<summary>, so it works with JavaScript disabled. */

  .faq { border-top: 1px solid var(--ww-border); }

  .faq__item { border-bottom: 1px solid var(--ww-border); }

  .faq__q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ww-space-4);
    padding: var(--ww-space-5) 0;
    font-size: var(--ww-step-1);
    font-weight: var(--ww-weight-semibold);
    color: var(--ww-ink);
    cursor: pointer;
    list-style: none;
  }

  .faq__q::-webkit-details-marker { display: none; }

  .faq__q::after {
    content: "";
    flex: none;
    width: 0.6rem;
    height: 0.6rem;
    border: solid var(--ww-primary);
    border-width: 0 2px 2px 0;
    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--ww-motion-base) var(--ww-motion-ease);
  }

  .faq__item[open] .faq__q::after { transform: translateY(2px) rotate(-135deg); }

  .faq__q:hover { color: var(--ww-primary); }

  .faq__a { padding-bottom: var(--ww-space-5); }

  .faq__a p { margin: 0; }

  /* -- Media frame -------------------------------------------------------- */

  .media {
    border-radius: var(--ww-radius-lg);
    overflow: hidden;
  }

  .media--shadow { box-shadow: var(--ww-shadow-lg); }

  /* -- Asset placeholder --------------------------------------------------- */
  /* Rendered by ww_img() while an asset's status is "todo", at the exact
     declared dimensions — so layouts are correct before artwork exists. */

  .ww-placeholder {
    display: grid;
    place-items: center;
    width: 100%;
    background:
      repeating-linear-gradient(
        45deg,
        var(--ww-surface) 0 10px,
        color-mix(in srgb, var(--ww-border) 45%, var(--ww-surface)) 10px 20px
      );
    border: 1px dashed var(--ww-border-input);
    border-radius: var(--ww-radius-lg);
    color: var(--ww-muted);
  }

  .ww-placeholder__label {
    padding: var(--ww-space-2) var(--ww-space-3);
    background: var(--ww-white);
    border-radius: var(--ww-radius-sm);
    font-family: var(--ww-font-mono);
    font-size: var(--ww-step--1);
    text-align: center;
  }

  .section--ink .ww-placeholder {
    background: repeating-linear-gradient(
      45deg,
      var(--ww-ink-soft) 0 10px,
      color-mix(in srgb, var(--ww-white) 6%, var(--ww-ink-soft)) 10px 20px
    );
    border-color: color-mix(in srgb, var(--ww-white) 25%, transparent);
  }

  .section--ink .ww-placeholder__label {
    background: var(--ww-ink);
    color: color-mix(in srgb, var(--ww-white) 70%, transparent);
  }

  /* -- Icon --------------------------------------------------------------- */

  .icon {
    flex: none;
    width: 1.5rem;
    height: 1.5rem;
  }

  /* -- Badge / chip ------------------------------------------------------- */

  .chip {
    display: inline-flex;
    align-items: center;
    padding: var(--ww-space-1) var(--ww-space-3);
    border-radius: var(--ww-radius-full);
    background: var(--ww-teal-100);
    color: var(--ww-teal-800);
    font-size: var(--ww-step--1);
    font-weight: var(--ww-weight-semibold);
  }

  .chip--accent { background: var(--ww-green-100); color: var(--ww-green-700); }

  /* Inline tag after a checklist line, e.g. "Module" or "Add-on". */
  .chip--sm {
    margin-inline-start: var(--ww-space-1);
    padding: 0 var(--ww-space-2);
    font-size: 0.72rem;
    line-height: 1.5;
    vertical-align: middle;
  }

  /* -- Checklist ---------------------------------------------------------- */

  .checklist {
    list-style: none;
    padding: 0;
  }

  .checklist li {
    position: relative;
    padding-inline-start: 2rem;
  }

  /* Circle. */
  .checklist li::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: 0.15em;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--ww-radius-full);
    background: var(--ww-teal-100);
    box-shadow: inset 0 0 0 1px var(--ww-teal-200);
  }

  /* Tick, drawn from two borders so it inherits the brand colour. */
  .checklist li::after {
    content: "";
    position: absolute;
    inset-inline-start: 0.44rem;
    top: 0.4em;
    width: 0.3rem;
    height: 0.55rem;
    border: solid var(--ww-primary);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
  }

  .section--ink .checklist li::before {
    background: color-mix(in srgb, var(--ww-teal-300) 20%, transparent);
    box-shadow: none;
  }

  .section--ink .checklist li::after { border-color: var(--ww-teal-300); }

  /* -- Showcase ------------------------------------------------------------ */
  /* Alternating text-beside-media rows. Shared by /, /software, and /app, so
     these live here rather than in a page sheet. */

  .showcase__row + .showcase__row { margin-top: var(--ww-space-11); }

  .showcase__row h3 { font-size: var(--ww-step-3); }

  .showcase__row .checklist li { font-size: var(--ww-step-0); }

  .showcase__body { align-self: center; }

  /* Portrait assets — the phone screens — are capped by an inline max-width
     from the template and would otherwise sit hard against one edge of a column
     they no longer fill. */
  .showcase__media { align-self: center; }

  .showcase__media .ww-placeholder,
  .showcase__media img { margin-inline: auto; }

  /* Grid layout: the same rows as cards, two across, media at the foot of
     each card so the row of screens lines up. The body stack keeps its gap;
     the card only adds the frame and pushes the media to the bottom edge. */
  .showcase__grid {
    display: grid;
    gap: var(--ww-space-6);
    margin-top: var(--ww-space-8);
  }

  @media (min-width: 768px) {
    .showcase__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  .showcase__card {
    display: flex;
    flex-direction: column;
    gap: var(--ww-space-6);
    padding: var(--ww-space-6) var(--ww-space-6) 0;
    background: var(--ww-white);
    border: 1px solid var(--ww-border);
    border-radius: var(--ww-radius-lg);
    overflow: hidden;
  }

  /* Text-only cards (no capture yet) close with normal padding. */
  .showcase__card--text { padding-bottom: var(--ww-space-6); }

  .showcase__card h3 { font-size: var(--ww-step-2); }

  .showcase__card .checklist li { font-size: var(--ww-step--1); }

  /* The screen sits flush at the foot of the card in a fixed 16:10 window,
     rounded only at the top, so it reads as a window into the product rather
     than a framed picture — and every card in a row ends at the same height.
     A portrait phone shot is capped by --media-max and cropped to its top. */
  .showcase__card .showcase__media {
    margin-top: auto;
    width: 100%;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: var(--ww-surface);
    border-radius: var(--ww-radius-md) var(--ww-radius-md) 0 0;
    box-shadow: var(--ww-shadow-md);
  }

  .showcase__card .showcase__media img,
  .showcase__card .showcase__media .ww-placeholder {
    display: block;
    width: 100%;
    max-width: var(--media-max, 100%);
    height: 100%;
    margin-inline: auto;
    object-fit: cover;
    object-position: top center;
  }

  /* Ledger layout: a stance column that stays put while the line items
     scroll past it. The items are divided by hairlines rather than boxed, so
     the section reads as an itemized statement, not a card grid. */
  .showcase__ledger { align-items: start; }

  .showcase__ledger .section-head { margin-bottom: 0; }

  .showcase__stance > * + * { margin-top: var(--ww-space-6); }

  .showcase__line {
    padding-block: var(--ww-space-7);
    border-top: 1px solid var(--ww-border);
  }

  .showcase__line:last-child { border-bottom: 1px solid var(--ww-border); }

  .showcase__line h3 { font-size: var(--ww-step-2); }

  .showcase__line .checklist li { font-size: var(--ww-step-0); }

  .showcase__line-label { display: block; margin-bottom: var(--ww-space-3); }

  @media (min-width: 768px) {
    .showcase__line {
      display: grid;
      grid-template-columns: 9rem minmax(0, 1fr);
      gap: var(--ww-space-6);
      align-items: start;
    }

    .showcase__line-label { margin-bottom: 0; padding-top: 0.45em; }
  }

  @media (min-width: 1024px) {
    .showcase__stance {
      position: sticky;
      top: calc(var(--ww-header-h, 4.5rem) + var(--ww-space-6));
    }
  }

  /* -- Panel callout ---------------------------------------------------------- */
  /* The same teal gradient card as the closing band, for one mid-page aside.
     Used by the ledger's commercial-model note; keep it to one per page so it
     stays a highlight rather than a pattern. */
  .callout.callout--panel {
    padding: var(--ww-space-6);
    border: 0;
    border-radius: var(--ww-radius-lg);
    background: linear-gradient(135deg, var(--ww-primary) 0%, var(--ww-teal-900) 100%);
    color: var(--ww-white);
    box-shadow: var(--ww-shadow-md);
  }

  .callout.callout--panel .callout__title { color: var(--ww-white); }

  .callout.callout--panel p { color: color-mix(in srgb, var(--ww-white) 85%, transparent); }

  .callout.callout--panel .callout__meta {
    margin-top: var(--ww-space-3);
    color: var(--ww-teal-300);
    font-weight: var(--ww-weight-semibold);
  }

  /* -- CTA band -------------------------------------------------------------- */
  /* The closing ask is a contained panel, not a full-bleed bar: a teal gradient
     card inside the container, text left and buttons right on wide screens, so
     it floats above the ink footer instead of merging with it. */
  .cta-band { padding-block: var(--ww-space-8) var(--ww-space-10); }

  main > .cta-band:last-child { padding-block-end: var(--ww-space-10); }

  .cta-band__panel {
    display: grid;
    gap: var(--ww-space-6);
    padding: clamp(2rem, 5vw, 3.5rem);
    border-radius: var(--ww-radius-xl);
    background: linear-gradient(135deg, var(--ww-primary) 0%, var(--ww-teal-900) 100%);
    color: var(--ww-white);
    box-shadow: var(--ww-shadow-lg);
  }

  @media (min-width: 900px) {
    .cta-band__panel {
      grid-template-columns: minmax(0, 1.4fr) auto;
      align-items: center;
      gap: var(--ww-space-9);
    }
  }

  .cta-band__text h2 {
    font-size: var(--ww-step-3);
    color: var(--ww-white);
    margin: 0;
  }

  .cta-band__text p {
    margin: var(--ww-space-3) 0 0;
    font-size: var(--ww-step-0);
    max-width: 36rem;
    color: color-mix(in srgb, var(--ww-white) 82%, transparent);
  }

  .cta-band__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ww-space-3);
  }

  @media (min-width: 900px) {
    .cta-band__actions { justify-content: flex-end; }
  }

  /* On the teal panel the primary button inverts to white and the secondary
     is a white outline, so the strongest action still reads as the strongest. */
  .cta-band .btn--primary {
    background: var(--ww-white);
    color: var(--ww-primary);
  }

  .cta-band .btn--primary:hover {
    background: var(--ww-teal-50);
    color: var(--ww-primary-hover);
  }

  .cta-band .btn--secondary {
    border-color: color-mix(in srgb, var(--ww-white) 55%, transparent);
    color: var(--ww-white);
  }

  .cta-band .btn--secondary:hover {
    background: var(--ww-white);
    color: var(--ww-primary);
    border-color: var(--ww-white);
  }

  /* -- Callout ------------------------------------------------------------- */
  /* An aside that qualifies the section it sits in — a definition, a caveat, a
     "what this actually means". Deliberately quieter than a card: no shadow and
     no hover, because it is never a link and should not invite a click. */

  .callout {
    max-width: var(--ww-measure);
    padding: var(--ww-space-5) var(--ww-space-6);
    background: var(--ww-teal-50);
    border-inline-start: 3px solid var(--ww-primary);
    border-radius: 0 var(--ww-radius-md) var(--ww-radius-md) 0;
    color: var(--ww-body);
  }

  .callout__title {
    margin-bottom: var(--ww-space-2);
    font-size: var(--ww-step-0);
    color: var(--ww-ink);
  }

  .callout__meta { margin-top: var(--ww-space-3); }

  .section--ink .callout {
    background: color-mix(in srgb, var(--ww-teal-300) 12%, transparent);
    border-inline-start-color: var(--ww-teal-300);
    color: color-mix(in srgb, var(--ww-white) 82%, transparent);
  }

  .section--ink .callout__title { color: var(--ww-white); }

  /* -- Prose --------------------------------------------------------------- */
  /* Running body copy: the mission text on /about, and every legal page. The
     measure is the point of it — an unconstrained paragraph in a wide column
     runs past 100 characters, which is where the eye starts losing its place
     on the return sweep. */

  .prose {
    max-width: var(--ww-measure);
    color: var(--ww-body);
  }

  .prose > * + * { margin-top: var(--ww-space-5); }

  .prose p { font-size: var(--ww-step-0); }

  /* The opening paragraph carries the section, so it is set a step larger.
     Scoped to the first child so it does not fire on a legal page where every
     paragraph would then be a lead. */
  .prose > p:first-child { font-size: var(--ww-step-1); color: var(--ww-ink); }

  /* -- Forms -------------------------------------------------------------- */

  .field { display: flex; flex-direction: column; gap: var(--ww-space-2); }

  .field label {
    font-size: var(--ww-step--1);
    font-weight: var(--ww-weight-semibold);
    color: var(--ww-ink);
  }

  /* width/min-width are load-bearing, not cosmetic. Without them a <select>
     takes the intrinsic width of its longest option — "Hosted CSMS and
     operator dashboard" — which at 320px is wider than its grid track, and a
     grid item's default `min-width: auto` lets that push the whole page wide.
     box-sizing: border-box is set globally, so the padding below is included. */
  .field :is(input, select, textarea) {
    width: 100%;
    min-width: 0;
    padding: var(--ww-space-3) var(--ww-space-4);
    background: var(--ww-white);
    border: 1px solid var(--ww-border-input);
    border-radius: var(--ww-radius-md);
    color: var(--ww-ink);
    transition: border-color var(--ww-motion-fast) var(--ww-motion-ease),
                box-shadow var(--ww-motion-fast) var(--ww-motion-ease);
  }

  /* No `outline: none` here. The site-wide :focus-visible ring in base.css is
     a solid 2px and is the actual indicator; a tinted shadow at low alpha
     computes to about 1.3:1 against white, which is no indicator at all. The
     border colour change stays as reinforcement. */
  .field :is(input, select, textarea):focus-visible {
    border-color: var(--ww-primary);
    /* base.css sets a radius on :focus-visible for links and buttons; without
       this the corners would visibly shrink the moment a field is focused. */
    border-radius: var(--ww-radius-md);
  }

  .field :is(input, textarea)::placeholder { color: var(--ww-muted); }

  .field--invalid :is(input, select, textarea) { border-color: var(--ww-error); }

  .field__error {
    font-size: var(--ww-step--1);
    color: var(--ww-error);
  }

  .field__required { color: var(--ww-error); }

  .field__hint {
    margin: 0;
    font-size: var(--ww-step--1);
    color: var(--ww-muted);
  }

  .field__optional {
    font-weight: var(--ww-weight-normal);
    color: var(--ww-muted);
  }

  /* Order matters: the hint sits between the label and the control, so it is
     read before the field is reached rather than after it is filled in.
     Direct children only — the consent row nests its own label and input, and
     a descendant selector here would reverse them. */
  .field > label { order: 1; }
  .field > .field__hint { order: 2; }
  .field > :is(input, select, textarea),
  .field > .choices { order: 3; }
  .field > .field__error { order: 4; }

  .consent {
    display: flex;
    align-items: start;
    gap: var(--ww-space-3);
  }

  /* 24px is the WCAG 2.2 AA minimum target (2.5.8). The label beside it is
     also clickable and spans the row, so the real target is much larger. */
  .consent input[type="checkbox"] {
    flex: none;
    width: 1.5rem;
    height: 1.5rem;
    margin-top: 0.05em;
    accent-color: var(--ww-primary);
  }

  .consent label {
    font-weight: var(--ww-weight-normal);
    font-size: var(--ww-step--1);
    color: var(--ww-body);
    cursor: pointer;
  }

  .field--consent { gap: var(--ww-space-2); }

  /* A radio group is a fieldset: same label weight on its legend, and the
     options drawn as rows a finger can hit. */
  .field--choice { min-width: 0; margin: 0; padding: 0; border: 0; }

  .field > legend.field__label {
    padding: 0;
    font-size: var(--ww-step--1);
    font-weight: var(--ww-weight-semibold);
    color: var(--ww-ink);
  }

  .choices {
    display: grid;
    gap: var(--ww-space-2);
  }

  .field .choice {
    display: flex;
    align-items: center;
    gap: var(--ww-space-3);
    padding: var(--ww-space-3) var(--ww-space-4);
    border: 1px solid var(--ww-border-input);
    border-radius: var(--ww-radius-md);
    background: var(--ww-white);
    font-size: var(--ww-step-0);
    font-weight: var(--ww-weight-normal);
    color: var(--ww-ink);
    cursor: pointer;
    transition: border-color var(--ww-motion-fast) var(--ww-motion-ease),
                background-color var(--ww-motion-fast) var(--ww-motion-ease);
  }

  .field .choice:hover { border-color: var(--ww-primary); }

  .field .choice:has(input:checked) {
    border-color: var(--ww-primary);
    background: var(--ww-teal-50);
  }

  .field .choice:has(input:focus-visible) {
    outline: 2px solid var(--ww-focus);
    outline-offset: 2px;
  }

  /* The row is the control; the native circle just needs to look like part of it. */
  .field .choice input[type="radio"],
  .field .choice input[type="checkbox"] {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    margin: 0;
    padding: 0;
    accent-color: var(--ww-primary);
  }

  .field .choice input[type="radio"]:focus-visible,
  .field .choice input[type="checkbox"]:focus-visible { outline: none; }

  .field--invalid .choice { border-color: var(--ww-error); }

  /* Honeypot — hidden from people, reachable by bots. */
  .honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
  }

  /* -- Alert -------------------------------------------------------------- */

  .alert {
    padding: var(--ww-space-4) var(--ww-space-5);
    border-radius: var(--ww-radius-md);
    border: 1px solid;
    font-size: var(--ww-step-0);
  }

  .alert--error {
    background: color-mix(in srgb, var(--ww-error) 8%, var(--ww-white));
    border-color: color-mix(in srgb, var(--ww-error) 35%, var(--ww-white));
    color: var(--ww-ink);
  }

  .alert ul { margin: 0; padding-inline-start: 1.1em; }
}
