/* shared/css/base.css -- GPFD base components
   (module redesign Phase 2; APP_MODULE_REDESIGN.md section 3.7)

   Link it straight after shared/css/tokens.css and before the page's own
   <style> (tokens.css shows the full order). tools/verify_shared_assets.py
   checks the order on every page that links it.

   EVERY RULE IS THE VERSION MOST PAGES ALREADY CARRY, value by value, counted
   across the 59 pages at b48419d -- so a page adopting this file can usually
   delete its own copy of a rule outright. Selectors are single classes on
   purpose: the page's own rule for the same selector comes later and wins.
   What the page's rule does NOT set still comes from here, which is the one
   thing to check when adopting (tools/redesign_page_snapshot.py compares a page
   before and after, pixel for pixel).

   Button heights follow the standard in CLAUDE.md section 6 and
   BUTTON_STANDARDIZATION.md: min-height, never vertical padding; desktop 31px,
   phone and body.content-narrow 38px; every class in all three lists.

   The last section styles what shared/js/core.js builds (GPFD.confirm,
   GPFD.panelError, GPFD.emptyState, and the HTML GPFD.formatMessage returns).
   core.js reads --gpfd-base to tell whether this file is linked. */

:root {
  --gpfd-base: 1;
}

/* ── Reset and page ground ─────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  /* iOS paints overscroll and the home-indicator strip with the background
     COLOUR, never the gradient image, and the default is white. */
  background-color: #050505;
  scrollbar-width: thin;
  scrollbar-color: rgba(212, 170, 44, 0.35) #0d0d0d;
}

body {
  font-family: var(--font);
  color: var(--text);
  min-height: 100vh;
  background:
    radial-gradient(ellipse 80% 50% at 50% -10%, rgba(201, 22, 34, 0.3), transparent),
    radial-gradient(ellipse 60% 40% at 80% 100%, rgba(212, 170, 44, 0.1), transparent),
    linear-gradient(180deg, #0f0d0c 0%, #161010 50%, #211410 100%);
  /* AFTER the shorthand: a `background` shorthand resets the attachment, which
     is how 15 pages lost it (REDESIGN_FINDINGS.md RF-031). */
  background-attachment: fixed;
}

::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-track {
  background: #0d0d0d;
  border-radius: 3px;
}
::-webkit-scrollbar-thumb {
  background: rgba(212, 170, 44, 0.35);
  border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
  background: rgba(212, 170, 44, 0.6);
}

/* ── Panels, tables, badges, states ────────────────────────────────────── */

.panel {
  background: rgba(10, 10, 10, 0.92);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  margin-bottom: 16px;
}

.panel-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-muted);
  margin-bottom: 16px;
}

/* Every table sits inside one, so a wide table scrolls instead of the page. */
.table-wrap {
  overflow-x: auto;
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.empty {
  text-align: center;
  padding: 40px;
  color: var(--text-faint);
  font-size: 14px;
}

.loading {
  text-align: center;
  padding: 40px;
  color: var(--text-faint);
  font-size: 13px;
}

.skeleton {
  background: linear-gradient(90deg, #141414, #1d1d1d, #141414);
  background-size: 200% 100%;
  animation: gpfd-shimmer 1.3s infinite;
  border-radius: var(--radius-sm);
}
@keyframes gpfd-shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

.form-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--gold);
  margin-bottom: 6px;
}

/* ── Button standard (CLAUDE.md section 6) ─────────────────────────────────
     generic  linear-gradient(180deg, #30291f, #171411)
              border 1px var(--border-strong) . color var(--gold)
     action   linear-gradient(180deg, #d21b28, #9d0008)
              border none . color #fff      the committing action           */

.btn-generic,
.btn-sm {
  background: linear-gradient(180deg, #30291f, #171411);
  border: 1px solid var(--border-strong);
  color: var(--gold);
}
.btn-generic:hover,
.btn-sm:hover {
  background: linear-gradient(180deg, #3a3126, #1d1915);
  border-color: var(--border-hover);
  color: var(--gold-light);
}

.btn-action,
.btn-primary {
  background: linear-gradient(180deg, #d21b28, #9d0008);
  border: none;
  color: #fff;
}
.btn-action:hover,
.btn-primary:hover {
  filter: brightness(1.1);
}

/* min-height is inert on an inline box, and an <a> is inline by default. */
a.btn-generic,
a.btn-action,
a.btn-sm,
a.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  text-decoration: none;
}

/* The shared box. The same list appears in all three height rules below. */
.btn-generic,
.btn-action,
.btn-sm,
.btn-primary,
.gpfd-confirm-cancel,
.gpfd-confirm-ok,
.gpfd-photo-cancel,
.gpfd-pv-close {
  min-height: 31px;
  padding-top: 4px;
  padding-bottom: 4px;
  font-family: var(--font);
  font-weight: 600;
  cursor: pointer;
  transition:
    filter 0.15s,
    background 0.15s,
    border-color 0.15s,
    color 0.15s;
}
@media (max-width: 700px) {
  .btn-generic,
  .btn-action,
  .btn-sm,
  .btn-primary,
  .gpfd-confirm-cancel,
  .gpfd-confirm-ok,
  .gpfd-photo-cancel,
  .gpfd-pv-close {
    min-height: 38px;
  }
}
body.content-narrow .btn-generic,
body.content-narrow .btn-action,
body.content-narrow .btn-sm,
body.content-narrow .btn-primary,
body.content-narrow .gpfd-confirm-cancel,
body.content-narrow .gpfd-confirm-ok,
body.content-narrow .gpfd-photo-cancel,
body.content-narrow .gpfd-pv-close {
  min-height: 38px;
}

/* Each class keeps only its radius, horizontal padding and font size. */
.btn-sm {
  border-radius: 6px;
  padding-left: 10px;
  padding-right: 10px;
  font-size: 12px;
  white-space: nowrap;
}
.btn-primary {
  border-radius: var(--radius);
  padding-left: 18px;
  padding-right: 18px;
  font-size: 13px;
}

/* .gold is the gold the base already carries; it survives as a hover accent. */
.btn-sm.gold:hover {
  background: var(--gold-pale);
}

/* Row-level destructive: generic fill, red ink. A table of ten rows must not
   become ten red buttons; the red fill is for the one committing action. */
.btn-sm.danger {
  border-color: rgba(201, 22, 34, 0.45);
  color: #ff5962;
}
.btn-sm.danger:hover {
  background: rgba(201, 22, 34, 0.14);
  border-color: rgba(201, 22, 34, 0.7);
  color: #ff7a82;
}

/* ── Modal shell ───────────────────────────────────────────────────────── */

.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  z-index: 500;
  /* RF-083: a dialog taller than the screen starts at its top and the overlay
     scrolls to its buttons; one that fits stays centred, exactly as before.
     "center" first is the fallback where "safe" is not supported (the
     bottom still scrolls into reach there). overscroll-behavior keeps the
     page behind still once the overlay reaches its end. */
  align-items: center;
  align-items: safe center;
  justify-content: center;
  padding: 24px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.modal-overlay.open {
  display: flex;
}

.modal {
  background: #111;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  max-width: 480px;
  width: 100%;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 22px;
  border-bottom: 1px solid var(--border);
}

.modal-title {
  font-family: var(--display);
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
  text-transform: uppercase;
}

/* An icon glyph: excluded from the button height bands (§6 exclusions). */
.modal-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-faint);
  font-size: 20px;
}

.modal-body {
  padding: 22px;
}

.modal-err {
  display: none;
  color: #ff5962;
  font-size: 13px;
  margin-top: 8px;
  padding: 8px 12px;
  background: rgba(201, 22, 34, 0.12);
  border: 1px solid rgba(201, 22, 34, 0.35);
  border-radius: var(--radius);
}

/* ── Widgets built by shared/js/core.js ────────────────────────────────── */

/* GPFD.confirm. Above page modals (500) and staffing overlays (1200); below the
   kebab menus (1300), toasts (1400) and the navbar popovers (1500). */
.gpfd-confirm-ov {
  position: fixed;
  inset: 0;
  z-index: 1250;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.8);
}

.gpfd-confirm {
  width: 100%;
  max-width: 380px;
  background: #111;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 28px 24px 24px;
  text-align: center;
}

.gpfd-confirm-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(201, 22, 34, 0.12);
  border: 1px solid rgba(201, 22, 34, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  margin: 0 auto 14px;
}
.gpfd-confirm-icon.warn {
  background: rgba(212, 170, 44, 0.12);
  border-color: rgba(212, 170, 44, 0.3);
}

.gpfd-confirm-title {
  font-family: var(--display);
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
  text-transform: uppercase;
  margin-bottom: 8px;
}

.gpfd-confirm-msg {
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.5;
  margin-bottom: 22px;
  overflow-wrap: anywhere;
}

.gpfd-confirm-row {
  display: flex;
  gap: 10px;
}

.gpfd-confirm-cancel,
.gpfd-confirm-ok {
  flex: 1;
  border-radius: var(--radius);
  padding-left: 16px;
  padding-right: 16px;
  font-size: 13px;
}
.gpfd-confirm-cancel {
  background: linear-gradient(180deg, #30291f, #171411);
  border: 1px solid var(--border-strong);
  color: var(--gold);
}
.gpfd-confirm-cancel:hover {
  background: linear-gradient(180deg, #3a3126, #1d1915);
  border-color: var(--border-hover);
  color: var(--gold-light);
}
.gpfd-confirm-ok {
  background: linear-gradient(180deg, #d21b28, #9d0008);
  border: none;
  color: #fff;
}
.gpfd-confirm-ok:hover {
  filter: brightness(1.1);
}

/* GPFD.choosePhoto. The same layer as GPFD.confirm: above the page modals it is
   opened from (500) and the staffing overlays (1200). On a phone it is a sheet
   on the bottom edge, where the thumb already is; wider, a centred box. */
.gpfd-photo-ov {
  position: fixed;
  inset: 0;
  z-index: 1250;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.8);
}

.gpfd-photo-sheet {
  width: 100%;
  max-width: 380px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: #111;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 18px 16px 16px;
}

.gpfd-photo-title {
  font-family: var(--display);
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  text-align: center;
  margin-bottom: 4px;
}

/* A sheet row -- a named exclusion from the 31/38px bands (CLAUDE.md section 6):
   the two choices ARE the sheet, taken with a thumb, often gloved. */
.gpfd-photo-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 50px;
  padding: 0 16px;
  background: linear-gradient(180deg, #30291f, #171411);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--gold);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition:
    background 0.15s,
    border-color 0.15s,
    color 0.15s;
}
.gpfd-photo-opt:hover,
.gpfd-photo-opt:focus-visible {
  background: linear-gradient(180deg, #3a3126, #1d1915);
  border-color: var(--border-hover);
  color: var(--gold-light);
}
.gpfd-photo-icon {
  font-size: 20px;
  line-height: 1;
  flex: none;
}

.gpfd-photo-cancel {
  width: 100%;
  margin-top: 4px;
  border-radius: var(--radius);
  padding-left: 16px;
  padding-right: 16px;
  font-size: 13px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
}
.gpfd-photo-cancel:hover {
  border-color: var(--border-hover);
  color: var(--text);
}

@media (max-width: 700px) {
  .gpfd-photo-ov {
    align-items: flex-end;
    padding: 0;
  }
  .gpfd-photo-sheet {
    max-width: none;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-bottom: none;
    padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  }
}

/* GPFD.viewPhoto: a photo full screen over the page, with a Close that is
   always on screen -- the app saved to a phone's home screen has no browser back
   button. Above GPFD.confirm (1250), so a photo opened from a dialog sits over
   it; below the kebab menus (1300), toasts (1400) and the navbar popovers. */
html.gpfd-pv-open,
html.gpfd-pv-open body {
  overflow: hidden;
}
.gpfd-pv {
  position: fixed;
  inset: 0;
  z-index: 1260;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0, 0.92);
}
.gpfd-pv-bar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: calc(10px + env(safe-area-inset-top, 0px)) 16px 10px;
}
.gpfd-pv-hint {
  font-size: 12px;
  color: var(--text-muted);
}
.gpfd-pv-close {
  flex: none;
  border-radius: var(--radius);
  padding-left: 16px;
  padding-right: 16px;
  font-size: 13px;
  background: linear-gradient(180deg, #30291f, #171411);
  border: 1px solid var(--border-strong);
  color: var(--gold);
}
.gpfd-pv-close:hover,
.gpfd-pv-close:focus-visible {
  background: linear-gradient(180deg, #3a3126, #1d1915);
  border-color: var(--border-hover);
  color: var(--gold-light);
}
.gpfd-pv-stage {
  flex: 1;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 16px calc(16px + env(safe-area-inset-bottom, 0px));
}
.gpfd-pv-img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 8px;
  cursor: zoom-in;
}
/* Zoomed: full size, and the stage scrolls -- from its edge, which a centred
   flex box would cut off. */
.gpfd-pv-stage.zoomed {
  display: block;
  padding: 0;
}
.gpfd-pv-stage.zoomed .gpfd-pv-img {
  max-width: none;
  max-height: none;
  border-radius: 0;
  cursor: zoom-out;
}

/* GPFD.panelError */
.gpfd-panel-error {
  text-align: center;
  padding: 28px 16px;
}
.gpfd-panel-error-icon {
  font-size: 22px;
  margin-bottom: 6px;
  opacity: 0.6;
}
.gpfd-panel-error-msg {
  color: #ff5962;
  font-size: 13px;
  overflow-wrap: anywhere;
}
.gpfd-panel-error-retry {
  margin-top: 10px;
}

/* GPFD.emptyState */
.gpfd-empty {
  text-align: center;
  padding: 40px 20px;
  color: var(--text-faint);
}
.gpfd-empty-icon {
  font-size: 36px;
  margin-bottom: 10px;
  opacity: 0.5;
}
.gpfd-empty-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.gpfd-empty-body {
  font-size: 12px;
}
.gpfd-empty-action {
  margin-top: 16px;
}

/* GPFD.formatMessage: a message's paragraphs, lists and links (CLAUDE.md
   section 102). The element carrying .gpfd-msg keeps its own font, size and
   colour; this restores only what the reset above took away -- the space
   between paragraphs, and the room a list's markers stand in -- and draws a
   link as one. */
.gpfd-msg {
  overflow-wrap: anywhere; /* a long address wraps rather than widening its card */
}
.gpfd-msg > * + * {
  margin-top: 0.65em;
}
.gpfd-msg ul,
.gpfd-msg ol {
  padding-left: 1.4em;
}
.gpfd-msg ul {
  list-style: disc;
}
.gpfd-msg ol {
  list-style: decimal;
}
.gpfd-msg li + li {
  margin-top: 0.25em;
}
.gpfd-msg strong {
  font-weight: 700;
  color: var(--text);
}
.gpfd-msg em {
  font-style: italic;
}
.gpfd-msg a {
  color: var(--gold-light);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.gpfd-msg a:hover {
  color: var(--gold);
}
