/* components.css — reusable UI components shared across pages: buttons, icon
   buttons, the form-control skin, the two-layer modal shell, toast, spinner, the
   panel card, footer primitives and the mobile-menu shell.
   Depends on tokens.css (and animations.css for the keyframes it references).
   Page CSS may specialise these but must not redefine or copy them. */

/* ---------- buttons ---------- */
/* HOVER IS FOR DEVICES THAT HOVER. Touch keeps :hover on the last tapped element until
   something else is tapped, so an unguarded rule leaves a control lit after every tap.
   Every hover rule in this file therefore sits behind @media(hover:hover) and
   (pointer:fine), with :active carrying the press feedback a finger does need. The
   keyboard ring is :focus-visible, never bare :focus - it sticks the same way. */
.btn{
  font-family:var(--sans);cursor:pointer;display:inline-flex;align-items:center;
  justify-content:center;gap:var(--sp-2);height:var(--ctrl-h);padding:0 var(--sp-5);
  border-radius:var(--radius-sm);font-size:.8rem;letter-spacing:.06em;border:1px solid transparent;
  line-height:1;white-space:nowrap;
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),transform var(--dur) var(--ease);
}
/* The base button IS a call to action: bordered, filling on hover - the same behaviour
   as Book Now on the marketing bar. It used to declare no colours at all, so every
   `.btn` without a modifier fell through to the browser's native grey chrome (System
   Center's Refresh, Retention's Run cleanup now, the section-reload notice). The
   variants below still override it; they are declared after this rule on purpose. */
.btn{background:transparent;border-color:var(--gold);color:var(--gold)}
@media(hover:hover) and (pointer:fine){.btn:hover:not(:disabled){background:var(--gold);color:var(--bg)}}
.btn:active:not(:disabled){background:var(--gold);color:var(--bg)}
.btn:disabled{opacity:.5;cursor:default;transform:none!important}
.btn-primary{background:var(--gold);color:var(--bg);font-weight:500;text-transform:uppercase;letter-spacing:.08em}
@media(hover:hover) and (pointer:fine){.btn-primary:hover:not(:disabled){background:var(--gold-soft);transform:translateY(-1px)}}
.btn-primary:active:not(:disabled){background:var(--gold-soft)}
/* `.btn-secondary` wears the SAME skin as the base .btn above - gold outline, gold
   label, gold fill with a dark label on hover - so every secondary control in the
   console reads like System > Refresh. It used to be a muted grey outline that on
   hover restated only `color`, keeping the base's gold FILL underneath: gold text on
   gold, and the label vanished on modal Cancel, the Audit/Logs Filter, Notifications
   Import/Export/Preview/History, the System database operations, Run test and the
   Data Lifecycle previews. Bare .btn escaped it by also flipping the text to --bg,
   which is why the GeoService toolbar looked right and hid the bug.
   A VARIANT MUST RESTATE BOTH background AND color in every state it styles; this one
   restates them explicitly rather than leaning on the cascade, so a future partial
   override is visible here. Guard: test_button_variants_restate_their_background. */
.btn-secondary{background:transparent;border-color:var(--gold);color:var(--gold)}
@media(hover:hover) and (pointer:fine){.btn-secondary:hover:not(:disabled){background:var(--gold);color:var(--bg)}}
.btn-secondary:active:not(:disabled){background:var(--gold);color:var(--bg)}
.btn-destructive{background:transparent;border-color:rgba(201,122,106,.5);color:var(--red)}
@media(hover:hover) and (pointer:fine){.btn-destructive:hover:not(:disabled){background:var(--red);color:#fff;border-color:var(--red)}}
.btn-destructive:active:not(:disabled){background:var(--red);color:#fff;border-color:var(--red)}
.btn-block{width:100%}
/* THE MARKETING CALLS TO ACTION - the same button, the marketing size. `.btn-gold` is
   the filled CTA and `.btn-ghost` the quiet one beside it (Book this / Message Us, the
   wizard's Continue / Back, the auth cards' submits). They carry their own geometry
   because a hero CTA is a bigger control than a console one; index.css and auth.css
   each used to declare a `.btn` of their own, and the auth card dressed its submit by
   element selector, so the three drifted. */
.btn-gold,.btn-ghost{height:auto;padding:16px 32px;border-radius:2px;font-size:.86rem;
  letter-spacing:.08em;text-transform:uppercase;text-decoration:none}
.btn-gold{background:var(--gold);color:var(--bg);border-color:var(--gold);font-weight:500}
@media(hover:hover) and (pointer:fine){.btn-gold:hover:not(:disabled){background:var(--gold-soft);border-color:var(--gold-soft);color:var(--bg);transform:translateY(-2px)}}
.btn-gold:active:not(:disabled){background:var(--gold-soft);border-color:var(--gold-soft);color:var(--bg)}
.btn-ghost{background:transparent;border-color:var(--line);color:var(--ink)}
@media(hover:hover) and (pointer:fine){.btn-ghost:hover:not(:disabled){background:transparent;border-color:var(--gold);color:var(--gold)}}
.btn-ghost:active:not(:disabled){background:transparent;border-color:var(--gold);color:var(--gold)}

/* icon-action: the shared row-action component. Monochrome, no per-action colour;
   meaning comes from shape + title + aria-label. */
.icon-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:var(--icon-btn);height:var(--icon-btn);border-radius:var(--radius-sm);flex:0 0 auto;cursor:pointer;
  background:transparent;border:1px solid var(--line);color:var(--ink-soft);
  transition:border-color var(--dur) var(--ease),color var(--dur) var(--ease),background var(--dur) var(--ease);
}
@media(hover:hover) and (pointer:fine){.icon-btn:hover:not(:disabled){border-color:var(--gold);color:var(--gold)}}
.icon-btn:active:not(:disabled){border-color:var(--gold);color:var(--gold)}
.icon-btn:disabled{opacity:.4;cursor:default}
.icon-btn svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* ---------- form controls ----------
   THE skin every field wears: one background, one border, one radius, one size for
   text inputs, selects, textareas, checkboxes and radios. Each toolbar used to bring
   its own copy or none at all, which is how System > Audit, System > Logs and the
   Payments filter ended up as white native iOS controls on a dark page.

   Wrapped in :where() so the whole block carries ZERO specificity - it is the floor a
   component specialises with an ordinary selector (the modal's full-width fields, a
   toolbar's flex sizing) instead of having to out-rank it.

   appearance:none is load-bearing, not cosmetic: iOS repaints a select and a checkbox
   with its own capsule whatever colours the page sets, so the arrow and the check mark
   have to be ours. They are inline data: URIs (both CSPs allow img-src data:); a CSS
   background cannot read a custom property, so those two glyphs carry the literal
   values of --ink-soft and --bg.

   Focus keeps base.css's :focus-visible ring - only the gold border is added here,
   because a text field showing its focus on any modality is correct (parent scope). */
:where(input:not([type=checkbox]):not([type=radio]):not([type=hidden]),select,textarea){
  appearance:none;
  height:var(--ctrl-h);padding:0 var(--sp-3);max-width:100%;
  background-color:var(--bg);border:1px solid var(--line-soft);border-radius:var(--radius-sm);
  color:var(--ink);font-family:var(--sans);font-size:.86rem;
}
:where(textarea){height:auto;min-height:70px;padding:10px var(--sp-3);line-height:1.4;resize:vertical}
:where(select){padding-right:var(--sp-8);background-repeat:no-repeat;
  background-position:right 10px center;background-size:12px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b3aa98' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E")}
:where(input,textarea)::placeholder{color:var(--ink-dim)}
/* iOS renders a date/time value in its own inner box that ignores the field's padding
   and centres itself; without this the value sits off the left edge every other field
   lines up on. */
:where(input[type=date],input[type=time])::-webkit-date-and-time-value{text-align:left}
/* Mobile Safari ZOOMS the page whenever a focused field is smaller than 16px, and it
   never zooms back out. The console's field size is 13.8px, so the fix is the field,
   not a viewport lock (user-scalable=no would take zoom away from everyone). Coarse
   pointer only - the desktop density is deliberate. */
@media(pointer:coarse){
  :where(input:not([type=checkbox]):not([type=radio]):not([type=hidden]),select,textarea){font-size:1rem}
}
:where(input,select,textarea):focus{border-color:var(--gold)}
:where(input,select,textarea):disabled{opacity:.55;cursor:not-allowed}

/* A checkbox is a 20px square in the palette. The comfortable TAP area is the label
   that wraps it, not the box: a pseudo-element overlay on an <input> is not rendered
   by Firefox, and padding the input would grow the painted square instead of the
   target. admin.css gives those labels their 44px on a coarse pointer. */
:where(input[type=checkbox],input[type=radio]){
  appearance:none;
  width:20px;height:20px;flex:0 0 auto;margin:0;padding:0;vertical-align:middle;cursor:pointer;
  background-color:var(--bg);border:1px solid var(--line);border-radius:var(--radius-sm);
  background-repeat:no-repeat;background-position:center;
  transition:background-color var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
:where(input[type=radio]){border-radius:var(--radius-round)}
:where(input[type=checkbox],input[type=radio]):checked{background-color:var(--gold);border-color:var(--gold)}
:where(input[type=checkbox]):checked{background-size:14px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230f0e0c' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E")}
:where(input[type=radio]):checked{box-shadow:inset 0 0 0 4px var(--bg)}

/* ---------- panel / card ---------- */
/* 22px padding is intentionally off the 4px scale — it is the established panel
   inset; keep it literal so tokenising never nudges the calendar layout. */
.panel{border:1px solid var(--line-soft);background:var(--panel);border-radius:var(--radius);padding:22px}

/* ---------- the human check's note ---------- */
/* Under the Turnstile slot (shared/human-check.js): the one line the provider's refusal
   is explained on. Centred small print in the danger ink; a page owns only its margin. */
.turnstile-note{margin:0;text-align:center;font-size:.82rem;color:var(--red)}
.turnstile-note[hidden]{display:none}

/* ---------- toast / spinner ---------- */
.toast{position:fixed;left:50%;bottom:28px;transform:translateX(-50%) translateY(20px);
  background:var(--gold);color:var(--bg);padding:11px 22px;border-radius:var(--radius);font-size:.84rem;
  font-weight:500;opacity:0;transition:all .3s;pointer-events:none;z-index:var(--z-toast)}
.toast.on{opacity:1;transform:translateX(-50%) translateY(0)}
.toast.err{background:var(--red);color:#fff}
.spin{display:inline-block;width:34px;height:34px;border:2px solid var(--line);
  border-top-color:var(--gold);border-radius:var(--radius-round);animation:sp .7s linear infinite}
.loading{text-align:center;padding:var(--sp-10) 0}

/* The back-to-top button moved to chrome.css: both chromes show it and this file
   is not loaded by the marketing pages, which is how the two copies drifted. */

/* ---------- mobile-menu shell (behaviour in shared-ui.js) ---------- */
body.menu-open{overflow:hidden}
/* .mob-body and the .mob-nav item list are the chrome's - the same owner the marketing
   menu reads, so the two cannot drift apart again. */

/* The footer lives in chrome.css - one owner for both the marketing pages and the
   console, which used to carry their own copies with different numbers. */
