/* =============================================================================
 * theme.css — shared light/dark design tokens, loaded before every other
 * stylesheet. The active theme is set server-side as <html data-theme="…">
 * (ThemeService — session → user profile → visitor cookie → admin default),
 * so there is no flash-of-wrong-theme: the correct token set is already
 * active on first paint.
 *
 * --gold / --ink / --bg are intentionally NOT defined here — those stay
 * admin-brand-configurable and are emitted per-layout by
 * _partials/theme_head.php, which writes BOTH the dark and the light values
 * (--gold is shared across both themes) so they survive a [data-theme] flip
 * made in the browser under the 'auto' default.
 * ========================================================================== */

:root {
  color-scheme: dark;

  /* Card / raised-surface backgrounds */
  --surface-1: #0b1220;
  --surface-2: rgba(255, 255, 255, .05);
  --surface-3: rgba(255, 255, 255, .08);

  /* Borders */
  --border-1: rgba(255, 255, 255, .1);
  --border-2: #1e293b;
  --border-3: #334155;

  /* Text */
  --text-1: #f1f5f9;
  --text-1b: #cbd5e1;
  --text-2: #94a3b8;
  /* Muted text still has to be readable. Measured against the two surfaces
     these are actually drawn on — the page (#04060A) and cards (#0d1524) —
     the previous values failed WCAG AA for body text: --text-3 was 4.26/3.84:1
     and --text-4 only 2.68/2.41:1, yet both carry real content (Sign out,
     table sub-labels, pager totals, stat captions, field hints). Lightened to
     the least amount that clears 4.5:1 on the worse surface while keeping a
     visible step between the four levels: the ladder is now 18.51 / 13.66 /
     7.91 / 6.49 / 5.43 on the page and 16.67 / 12.30 / 7.12 / 5.85 / 4.89 on
     cards — monotonic, and every level clears AA.
     The light theme already passed and is unchanged. */
  --text-3: #8593a6;
  /* #78859a cleared AA against the page (5.0) but not against the raised
     surfaces painted on top of it: 4.47 on surface-2 and 4.11 on surface-3.
     #808da2 clears all three (5.6 / 4.97 / 4.57) and stays the faintest tier. */
  --text-4: #808da2;

  /* Form inputs */
  --input-bg: rgba(255, 255, 255, .05);
  --input-border: rgba(255, 255, 255, .1);

  /* Status/accent hues — used as TEXT colour inside low-alpha tinted chips
     (badges, alerts, action buttons). The chip backgrounds themselves stay
     literal rgba(...) since a low-alpha tint reads fine over either base;
     only the foreground pastel needs to darken in light mode for contrast. */
  --c-green:  #86efac;
  --c-red:    #fca5a5;
  /* Solid red for use AS A BACKGROUND behind white text (the --c-* reds above
     are foreground colours). White on this is 6.47:1 — AA for normal text. */
  --c-danger-bg: #b91c1c;
  --c-amber:  #fde047;
  --c-orange: #fdba74;
  --c-purple: #c4b5fd;
  --c-indigo: #a5b4fc;
  --c-cyan:   #7dd3fc;
  --c-blue:   #93c5fd;

  /* Text-role variant of the brand gold: identical to --gold on dark
     backgrounds (kept byte-identical here), but --gold itself (#C9A24B) only
     measures ~2.2:1 as TEXT on the light page bg — see the light override
     below for the AA-passing value. Use --gold-text for `color:` on gold,
     keep --gold for borders/backgrounds/accents (those don't need this). */
  --gold-text: var(--gold, #C9A24B);
}

:root[data-theme="light"] {
  color-scheme: light;

  --surface-1: #ffffff;
  --surface-2: rgba(15, 23, 42, .04);
  --surface-3: rgba(15, 23, 42, .07);

  --border-1: rgba(15, 23, 42, .12);
  --border-2: #e2e8f0;
  --border-3: #cbd5e1;

  --text-1: #0f172a;
  --text-1b: #334155;
  --text-2: #475569;
  /* NOTE: on the light page bg (#F4F6F9), the dark-theme value #64748b only
     clears ~4.4:1 — fails WCAG AA (needs 4.5:1) on <th> headers and
     .stat-label captions. #57647a clears ~5.5:1 with margin. */
  --text-3: #57647a;
  /* NOTE: the faintest tier can't go as light as the dark theme's does —
     on the light page bg (#F4F6F9), #94a3b8 gives only ~2.4:1 and even
     #64748b lands at ~4.4:1, both failing WCAG AA for the hint text
     (`.form-group small`) that uses it. #5e6d80 cleared 4.5:1 against the page
     background, but the hosted cards sit on a tinted surface (~#eaecef) where
     the same colour lands at 4.46:1 — just under. #5c6b7e clears 4.5:1 on the
     card too (4.60) and is still the faintest tier by eye. */
  --text-4: #5c6b7e;

  --input-bg: #ffffff;
  --input-border: rgba(15, 23, 42, .16);

  /* --gold (#C9A24B, or the admin's custom brand gold) is a light/mid tone
     picked to sit on a DARK background — as TEXT on the light page bg it
     measures only ~2.2:1. Darkened here to ~5.3:1 while staying a
     recognizably gold/amber hue. Borders/backgrounds/accents keep --gold
     itself (unaffected — text contrast rules don't apply there). */
  --gold-text: #7d621b;

  /* Darker/more-saturated so text stays legible on a light chip background.
     --c-green further darkened from #15803d (only ~4.2:1) to clear AA. */
  --c-green:  #0e6b32;
  --c-red:    #b91c1c;
  --c-danger-bg: #b91c1c;   /* white on this is 6.47:1 — AA */
  --c-amber:  #8a5406;
  --c-orange: #c2410c;
  --c-purple: #6d28d9;
  --c-indigo: #4338ca;
  --c-cyan:   #0e7490;
  --c-blue:   #1d4ed8;
}

/* Native <select> option popups follow the active theme. A translucent author
   background on a <select> makes Chromium composite the open option list over
   its default white menu backdrop (washed-white list in dark mode); giving the
   options a SOLID token background fixes it everywhere. Tokens flip under
   [data-theme="light"], so this is automatically light/dark correct. Comboboxes
   hide their native <select> (display:none), so these options never render. */
select option,
select optgroup {
  background-color: var(--surface-1);
  color: var(--text-1);
}

/* Requirement / status rows (install wizard + Admin → Settings → Server).
   The status column used to be white-space:nowrap, which meant a longer
   translation could not wrap: it squeezed the label column until words broke
   apart mid-row. Nothing here is nowrap and both columns may wrap, so the
   layout holds for any language regardless of string length. Long detail text
   sits on its own line under the label rather than fighting for the right
   column. */
.check-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: .75rem;
  padding: .5rem 0;
  border-bottom: 1px solid color-mix(in srgb, var(--text-1) calc(.06 * 100%), transparent);
  font-size: .9rem;
}
.check-row:last-child { border-bottom: 0; }

.check-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}
.check-opt {
  color: var(--text-3);
  font-size: .78rem;
  white-space: nowrap;
}
.check-detail {
  display: block;
  margin-top: .15rem;
  font-size: .75rem;
  color: var(--text-3);
  overflow-wrap: anywhere;
}

.check-state {
  flex: 0 1 auto;
  text-align: right;
  overflow-wrap: anywhere;
}
.check-state.is-ok    { color: var(--c-green); }
.check-state.is-warn  { color: var(--c-amber); }
.check-state.is-bad   { color: var(--c-red); }
.check-state.is-muted { color: var(--text-3); }

/* ---- Username availability status ----
   Rendered by _partials/username_check.php, which is included from BOTH the
   auth layout (registration) and the panel layout (member + admin profile
   forms). These rules used to be duplicated verbatim in auth.css and
   panel.css, so the two copies could drift. theme.css is loaded by every
   layout, which makes it the one place a shared partial's styles belong. */
.username-status--checking  { color: var(--text-3); }
.username-status--available { color: var(--c-green); }
.username-status--taken,
.username-status--invalid   { color: var(--c-red); }

/* ---- Screen-reader-only utility ----
   For text that must exist for assistive tech but not visually — icon-only
   buttons, table captions, live-region status. Clipped rather than
   display:none, which would remove it from the accessibility tree too. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- Keyboard focus ----
   Form controls across the app set `outline: none` to replace the browser's
   default ring with a border-colour change. That reads fine with a mouse and
   badly without one: a border tint is far below the 3:1 non-text contrast
   WCAG 2.4.7 expects, and on some controls there was no visible change at all.
   :focus-visible only fires for keyboard/programmatic focus, so this restores a
   clear ring for keyboard users without putting one back on every mouse click.

   `!important` is load-bearing, not laziness. :where() deliberately zeroes its
   own arguments, so this selector's specificity is just :focus-visible — (0,1,0).
   The rules it has to beat set `outline: none` UNCONDITIONALLY (not on :focus)
   at up to (0,2,1), e.g. `.form-group input[type="text"]` in panel.css, and
   theme.css loads first. Without !important the ring loses on every panel and
   auth form control — verified in the browser before this was added. Dropping
   :where() would not help either: the ring would still have to out-specify each
   of those selectors individually. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--gold, #C9A24B) !important;
  outline-offset: 2px !important;
  border-radius: 4px;
}

/* ---- Reduced motion ----
   Honour the OS "reduce motion" setting. Nothing in the UI depends on
   animation to convey meaning, so this is safe to apply broadly. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---- Confirmation dialog (assets/js/app.js) ----
   Replaces the native confirm(), which could not be themed or translated
   beyond its message and blocked the main thread. */
.confirm-dialog {
  border: 1px solid var(--border-2, #1e293b);
  border-radius: 12px;
  /* --surface-1 (opaque), NOT --surface-2: surface-2 is a 4-5% translucent
     tint meant to sit ON a page, but a <dialog> composites over its own
     ::backdrop. In light theme the dialog body therefore resolved to mid-dark
     grey under near-black --text-1 — about 2.95:1, below AA. The literal
     fallback here was already an opaque colour, which is what was intended. */
  background: var(--surface-1, #0f172a);
  color: var(--text-1, #e2e8f0);
  padding: 0;
  max-width: min(28rem, calc(100vw - 2rem));
  box-shadow: 0 20px 50px rgba(0, 0, 0, .45);
  /* A modal <dialog> is centred by the user agent's own `margin: auto` against
     `inset: 0`. Every panel stylesheet opens with `*, *::before, *::after {
     margin: 0 }`, which wins over that UA rule and pinned the dialog to the
     top-left corner of the viewport. Restoring auto margins here re-centres it
     — this affected every confirm dialog in the product, not one screen. */
  margin: auto;
}
.confirm-dialog::backdrop { background: rgba(2, 6, 12, .6); }
.confirm-dialog__inner   { padding: 1.5rem; margin: 0; }
.confirm-dialog__msg     { margin: 0 0 1.25rem; font-size: .95rem; line-height: 1.5; }
/* The optional note. Its wrapper is a <label> holding the caption and the
   input, so by default the field sat on the same line as its own text and took
   whatever width was left. Block layout puts the field on its own line at full
   width, with breathing room above it and before the buttons. */
/* The prompt row is opt-in: app.js sets [hidden] unless the form asked for a
   note (data-prompt + data-prompt-field, used by bank transfers and
   withdrawals). An author `display` rule OUTRANKS the UA stylesheet's
   `[hidden] { display: none }`, so without the guard below the attribute was
   silently ignored and every confirm dialog — including deletes — showed an
   unlabelled input whose value went nowhere. */
.confirm-dialog__promptwrap[hidden] { display: none; }
.confirm-dialog__promptwrap  { display: block; margin: 0 0 1.25rem; }
.confirm-dialog__promptlabel { display: block; margin-bottom: .4rem; font-size: .9rem; }
.confirm-dialog__prompt      { display: block; width: 100%; box-sizing: border-box; }

.confirm-dialog__actions { display: flex; gap: .6rem; justify-content: flex-end; }

/* The dialog's own buttons.
   buildDialog() hard-codes class="btn-outline-sm" / "btn-primary-sm" on them,
   and those two are defined ONLY in panel.css — which the PUBLIC layout does
   not load. So on a public page (the booking-manage screen is the one that
   calls confirm()) both buttons rendered as bare browser default controls in
   a themed dialog. Styling them here, beside the rest of the dialog, means
   they are covered wherever the dialog can appear. Panel pages are unaffected:
   panel.css loads after this file and its .btn-*-sm rules still win. */
.confirm-dialog__cancel {
  background: none; border: 1px solid var(--border-3, #334155); color: var(--text-2, #94a3b8);
  border-radius: 6px; padding: .35rem .85rem; font-size: .8rem; cursor: pointer;
}
.confirm-dialog__cancel:hover { border-color: var(--gold); color: var(--gold-text); }
.confirm-dialog__ok {
  display: inline-block; padding: .45rem 1rem; background: var(--gold, #C9A24B);
  color: var(--ink, #0A0F16); font-size: .82rem; font-weight: 700; border-radius: 6px;
  text-decoration: none; border: none; cursor: pointer; transition: opacity .15s;
}
.confirm-dialog__ok:hover { opacity: .88; }
.confirm-dialog__ok.is-danger {
  /* --c-danger-bg, not --c-red: the --c-* reds are documented above as
     FOREGROUND colours, and in dark theme --c-red is the pastel #fca5a5, so
     white-on-pastel measured 1.90:1 and the destructive button read as
     disabled. --c-danger-bg is a solid red defined for both themes. */
  background: var(--c-danger-bg, #b91c1c);
  color: #fff;
}
