/*
  Kudafushi Complaints & Requests — shared design system (2026 refresh)
  Palette matched to the guest site suite (denorth.html / pdf-viewer.html):
  void/gold luxury theme, dark by default with a light override.
  Import this once per page, then add only page-specific rules locally.
*/

:root{
  /* --- surface & ink (dark, default) --- */
  --kf-parchment:      #0E0B08;
  --kf-parchment-deep: #1A1510;
  --kf-surface:        #1A1510;
  --kf-surface-soft:   #221C14;
  --kf-ink:            #F2E8D9;
  --kf-ink-soft:       rgba(242,232,217,0.62);
  --kf-ink-faint:      rgba(242,232,217,0.4);

  /* --- brand --- */
  --kf-ocean:          #D1B4A1;
  --kf-ocean-deep:     #16110B;
  --kf-gold:           #B89B89;
  --kf-gold-soft:      #D1B4A1;
  --kf-gold-wash:      rgba(184,155,137,0.1);

  /* --- line & state --- */
  --kf-line:           rgba(184,155,137,0.22);
  --kf-line-soft:      rgba(184,155,137,0.1);
  --kf-ok:             #6FB08D;
  --kf-ok-bg:           rgba(111,176,141,0.14);
  --kf-warn:           #D6A15A;
  --kf-warn-bg:        rgba(209,161,90,0.14);
  --kf-late:           #D08770;
  --kf-late-bg:        rgba(208,135,112,0.14);

  /* --- shape & elevation --- */
  --kf-radius-sm:      9px;
  --kf-radius:         14px;
  --kf-radius-lg:      22px;
  --kf-radius-pill:    999px;
  --kf-shadow-sm:      0 2px 12px rgba(0,0,0,0.35);
  --kf-shadow:         0 10px 34px rgba(0,0,0,0.45);
  --kf-shadow-lg:      0 24px 64px rgba(0,0,0,0.55);
  --kf-ring:           0 0 0 3px var(--kf-gold-wash);

  /* --- layout --- */
  --kf-topbar-h:        63px; /* 16px+16px padding + 30px logo/icon row + 1px border */

  /* --- type --- */
  --kf-font-display:   'Playfair Display', Georgia, 'Times New Roman', serif;
  --kf-font-body:      'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  color-scheme: dark;
}

/* Auto light mode when the OS prefers light and no explicit choice was made */
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]){
    --kf-parchment:      #FDFBF8;
    --kf-parchment-deep: #F2ECE5;
    --kf-surface:        #FFFFFF;
    --kf-surface-soft:   #F2ECE5;
    --kf-ink:            #1C1410;
    --kf-ink-soft:       rgba(28,20,16,0.62);
    --kf-ink-faint:      rgba(28,20,16,0.4);

    --kf-ocean:          #7D6355;
    --kf-ocean-deep:     #2A1B12;
    --kf-gold:           #9E806D;
    --kf-gold-soft:      #B89B89;
    --kf-gold-wash:      rgba(140,116,104,0.08);

    --kf-line:           rgba(140,116,104,0.25);
    --kf-line-soft:      rgba(140,116,104,0.12);
    --kf-ok:             #3E7A5C;
    --kf-ok-bg:           #DCEEE1;
    --kf-warn:           #A9702B;
    --kf-warn-bg:        #F1DFC2;
    --kf-late:           #AE4A36;
    --kf-late-bg:        #F5DAD2;

    --kf-shadow-sm:      0 2px 10px rgba(37,29,20,0.06);
    --kf-shadow:         0 10px 32px rgba(37,29,20,0.10);
    --kf-shadow-lg:      0 24px 60px rgba(37,29,20,0.16);

    color-scheme: light;
  }
}

/* Explicit choice via the theme toggle (kfToggleTheme in theme.js) always wins */
[data-theme="light"]{
  --kf-parchment:      #FDFBF8;
  --kf-parchment-deep: #F2ECE5;
  --kf-surface:        #FFFFFF;
  --kf-surface-soft:   #F2ECE5;
  --kf-ink:            #1C1410;
  --kf-ink-soft:       rgba(28,20,16,0.62);
  --kf-ink-faint:      rgba(28,20,16,0.4);

  --kf-ocean:          #7D6355;
  --kf-ocean-deep:     #2A1B12;
  --kf-gold:           #9E806D;
  --kf-gold-soft:      #B89B89;
  --kf-gold-wash:      rgba(140,116,104,0.08);

  --kf-line:           rgba(140,116,104,0.25);
  --kf-line-soft:      rgba(140,116,104,0.12);
  --kf-ok:             #3E7A5C;
  --kf-ok-bg:           #DCEEE1;
  --kf-warn:           #A9702B;
  --kf-warn-bg:        #F1DFC2;
  --kf-late:           #AE4A36;
  --kf-late-bg:        #F5DAD2;

  --kf-shadow-sm:      0 2px 10px rgba(37,29,20,0.06);
  --kf-shadow:         0 10px 32px rgba(37,29,20,0.10);
  --kf-shadow-lg:      0 24px 60px rgba(37,29,20,0.16);

  color-scheme: light;
}

[data-theme="dark"]{
  --kf-parchment:      #0E0B08;
  --kf-parchment-deep: #1A1510;
  --kf-surface:        #1A1510;
  --kf-surface-soft:   #221C14;
  --kf-ink:            #F2E8D9;
  --kf-ink-soft:       rgba(242,232,217,0.62);
  --kf-ink-faint:      rgba(242,232,217,0.4);

  --kf-ocean:          #D1B4A1;
  --kf-ocean-deep:     #16110B;
  --kf-gold:           #B89B89;
  --kf-gold-soft:      #D1B4A1;
  --kf-gold-wash:      rgba(184,155,137,0.1);

  --kf-line:           rgba(184,155,137,0.22);
  --kf-line-soft:      rgba(184,155,137,0.1);
  --kf-ok:             #6FB08D;
  --kf-ok-bg:           rgba(111,176,141,0.14);
  --kf-warn:           #D6A15A;
  --kf-warn-bg:        rgba(209,161,90,0.14);
  --kf-late:           #D08770;
  --kf-late-bg:        rgba(208,135,112,0.14);

  --kf-shadow-sm:      0 2px 12px rgba(0,0,0,0.35);
  --kf-shadow:         0 10px 34px rgba(0,0,0,0.45);
  --kf-shadow-lg:      0 24px 64px rgba(0,0,0,0.55);

  color-scheme: dark;
}

*, *::before, *::after{ box-sizing: border-box; }
/* scroll-behavior is deliberately "auto", not "smooth". With "smooth" set
   on <html>, the browser ANIMATES scroll restoration when you press Back —
   so returning to a list you'd scrolled down slowly crawls back into
   position instead of just being there. Anywhere this site genuinely wants
   a smooth scroll, it asks for one explicitly with
   scrollIntoView({behavior:'smooth'}), which is unaffected by this. */
html{ -webkit-text-size-adjust: 100%; font-size: 115%; scroll-behavior: auto; overflow-x: hidden; overflow-x: clip; scrollbar-width: none; -webkit-tap-highlight-color: transparent; }
*{ -webkit-tap-highlight-color: transparent; }
/* Text on the staff pages is SELECTABLE. It used to be blocked on table
   rows and cells, which also blocked the everyday need to copy a staff
   name, a username, an email address, a villa number or a ticket ID out
   of a list. That is a normal thing to want to do at a desk and there was
   no way to do it.

   The original reason was touch: a row that navigates when tapped
   shouldn't flash a text highlight when long-pressed. That still holds,
   so the block is kept for genuine CONTROLS — buttons, drawer links, bell
   items — and only on touch devices. Content is always selectable, on
   every device. Long-pressing a table cell on a phone to copy a villa
   number is a legitimate thing to do, not an accident. */
.kf-table tr, .kf-table td, .kf-dept-card,
.kf-card, .kf-lede, .kf-page-title, .kf-file-meta, .kf-file-title{
  -webkit-user-select: text;
  user-select: text;
}
@media (hover: none) and (pointer: coarse){
  .kf-btn, .drawer-link, .kf-bell-item{
    -webkit-user-select: none;
    user-select: none;
  }
}
html::-webkit-scrollbar{ display: none; }
body::-webkit-scrollbar{ display: none; }
body{ scrollbar-width: none; }

body.kf-body{
  margin: 0;
  min-height: 100vh;
  overflow-x: clip;
  -webkit-overflow-scrolling: touch;
  background: var(--kf-parchment);
  color: var(--kf-ink);
  font-family: var(--kf-font-body);
  font-weight: 300;
  line-height: 1.55;
  transition: background .25s ease, color .25s ease;
}

.kf-body h1, .kf-body h2, .kf-body h3{
  font-family: var(--kf-font-display);
  font-weight: 300;
  margin: 0;
  color: var(--kf-ink);
  letter-spacing: -0.01em;
}

.kf-body a{ color: var(--kf-ocean); text-decoration: none; }
@media (hover: hover) and (pointer: fine){ .kf-body a:hover{ text-decoration: underline; } }

.kf-body :focus-visible{
  outline: 2px solid var(--kf-gold);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce){
  .kf-body *{ transition: none !important; animation: none !important; }
  html{ scroll-behavior: auto; }
}

/* ---------------- Layout shells ---------------- */

/* Centered auth-style card (login, change/forgot/reset password, setup) */
.kf-auth-shell{
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 28px 20px;
}
.kf-theme-toggle-fixed{
  position: absolute; top: 18px; right: 18px;
}
.kf-theme-toggle-fixed .kf-icon-btn{
  background: var(--kf-surface); border-color: var(--kf-line); color: var(--kf-ink-soft);
}
@media (hover: hover) and (pointer: fine){ .kf-theme-toggle-fixed .kf-icon-btn:hover{ background: var(--kf-surface-soft); } }

.kf-card{
  background: var(--kf-surface);
  border: 1px solid var(--kf-line);
  border-radius: var(--kf-radius-lg);
  box-shadow: var(--kf-shadow);
  padding: 32px 30px;
  width: 100%;
  max-width: 380px;
}

.kf-card--wide{ max-width: 460px; }

.kf-card .kf-logo{
  display: block;
  height: 34px;
  width: auto;
  margin: 0 auto 18px;
}

.kf-eyebrow{
  color: var(--kf-gold);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  font-size: .7rem;
  margin-bottom: 6px;
  display: block;
}

.kf-sub{
  font-size: .85rem;
  color: var(--kf-ink-soft);
  margin: 4px 0 4px;
  line-height: 1.5;
}

.kf-back{
  display: block;
  text-align: center;
  margin-top: 18px;
  font-size: .82rem;
  color: var(--kf-gold);
  font-weight: 600;
}

/* Full-width app shell (submit, staff, admin_users) */
.kf-topbar{
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: 16px 22px;
  background: var(--kf-parchment);
  background-clip: padding-box;
  opacity: 1;
  color: var(--kf-ink);
  border-bottom: 1px solid var(--kf-line);
  box-shadow: var(--kf-shadow-sm);
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
  position: sticky;
  top: 0;
  z-index: 850;
  isolation: isolate;
}

.kf-topbar .kf-brand{ display: flex; align-items: center; gap: 10px; text-decoration: none; cursor: pointer; transition: opacity .15s ease; grid-column: 2; justify-self: center; }
@media (hover: hover) and (pointer: fine){ .kf-topbar .kf-brand:hover{ opacity: .8; text-decoration: none; } }
.kf-topbar .kf-brand img{ height: 30px; width: auto; display: block; }

.kf-topbar .kf-nav-back{ grid-column: 1; justify-self: start; }
.kf-topbar .kf-topbar-right{ grid-column: 3; justify-self: end; display: flex; align-items: center; gap: 10px; position: relative; }

.kf-nav-back{
  display: flex; align-items: center; gap: 7px;
  font-size: 14px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--kf-gold-soft); text-decoration: none !important; cursor: pointer;
  background: none; border: none; padding: 0; font-family: inherit;
  transition: color .15s ease;
}
@media (hover: hover) and (pointer: fine){ .kf-nav-back:hover{ color: var(--kf-ink); } }
.kf-nav-back i{ font-size: 15px !important; }

.kf-topbar-actions{ display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }


.kf-icon-btn{
  background: var(--kf-surface);
  border: 1px solid var(--kf-line-soft);
  color: var(--kf-gold-soft);
  border-radius: var(--kf-radius-pill);
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background .15s ease, transform .15s ease, border-color .15s ease;
}
@media (hover: hover) and (pointer: fine){ .kf-icon-btn:hover{ border-color: var(--kf-gold); } }
.kf-icon-btn i.ti{ font-size: 17px !important; }

.kf-bell-btn{ position: relative; text-decoration: none !important; }
.kf-bell-badge{
  position: absolute; top: -4px; right: -4px;
  min-width: 16px; height: 16px; padding: 0 3px;
  border-radius: var(--kf-radius-pill);
  background: var(--kf-late); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
  box-shadow: 0 0 0 2px var(--kf-parchment-deep);
}

.kf-bell-wrap{ /* positioning anchor moved to .kf-topbar-right below, so the dropdown aligns to the true right edge of the header regardless of how many icon buttons sit next to the bell */ }
.kf-bell-panel{
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 950;
  width: 320px; max-width: calc(100vw - 32px);
  background: var(--kf-surface); border: 1px solid var(--kf-line); border-radius: var(--kf-radius);
  box-shadow: var(--kf-shadow); overflow: hidden;
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.kf-bell-panel.is-open{ opacity: 1; transform: translateY(0); pointer-events: auto; }
.kf-bell-panel-head{
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--kf-line-soft);
}
.kf-bell-panel-head strong{ font-family: var(--kf-font-display); font-size: 1rem; color: var(--kf-ink); }
.kf-bell-panel-count{ font-size: .72rem; color: var(--kf-ink-faint); }
.kf-bell-panel-list{ max-height: 360px; overflow-y: auto; }
.kf-bell-empty{ padding: 22px 14px; text-align: center; color: var(--kf-ink-faint); font-size: .82rem; }
.kf-bell-item{
  display: block; padding: 10px 14px; text-decoration: none !important;
  border-bottom: 1px solid var(--kf-line-soft); transition: background .12s ease;
}
.kf-bell-item:last-child{ border-bottom: none; }
@media (hover: hover) and (pointer: fine){ .kf-bell-item:hover{ background: var(--kf-gold-wash); } }
.kf-bell-item-top{ display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 3px; }
.kf-bell-item-id{ font-size: .78rem; font-weight: 700; color: var(--kf-ink); }
.kf-bell-item-detail{ display: block; font-size: .74rem; color: var(--kf-gold-soft); margin-bottom: 2px; }
.kf-bell-item-snippet{ display: block; font-size: .8rem; color: var(--kf-ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kf-bell-panel-footer{
  display: block; text-align: center; padding: 10px; font-size: .8rem; font-weight: 600;
  color: var(--kf-gold); text-decoration: none !important; border-top: 1px solid var(--kf-line-soft);
}
@media (hover: hover) and (pointer: fine){ .kf-bell-panel-footer:hover{ background: var(--kf-gold-wash); } }
@media (hover: hover) and (pointer: fine){ .kf-icon-btn:hover{ background: var(--kf-surface-soft); border-color: var(--kf-gold); transform: translateY(-1px); } }

.kf-main{
  max-width: 2000px;
  width: 100%;
  margin: 0 auto;
  padding: 28px 32px 72px;
}

.kf-dash-header{
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 22px;
}
.kf-dash-header .kf-meta{ font-size: .82rem; line-height: 1.7; color: var(--kf-ink-soft); }
.kf-dash-header .kf-meta strong{ color: var(--kf-ink); }
.kf-dash-header .kf-meta a{ font-weight: 600; }
.kf-dash-header .kf-meta i{ margin-right: 4px; }

/* ---------------- Type helpers ---------------- */
.kf-lede{ color: var(--kf-ink-soft); margin-top: 8px; font-size: .95rem; max-width: 60ch; }

/* ---------------- Forms ---------------- */
.kf-field{ margin-bottom: 16px; }
.kf-body label{
  display: block;
  font-weight: 600;
  font-size: .82rem;
  margin: 14px 0 6px;
  color: var(--kf-ink);
}
.kf-body label:first-of-type{ margin-top: 0; }

.kf-body input[type="text"],
.kf-body input[type="password"],
.kf-body input[type="email"],
.kf-body input,
.kf-body select,
.kf-body textarea{
  width: 100%;
  padding: 11px 12px;
  border-radius: var(--kf-radius-sm);
  border: 1px solid var(--kf-line);
  background: var(--kf-surface-soft);
  color: var(--kf-ink);
  font-family: var(--kf-font-body);
  font-size: .95rem;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.kf-body input:focus,
.kf-body select:focus,
.kf-body textarea:focus{
  outline: none;
  border-color: var(--kf-gold);
  box-shadow: var(--kf-ring);
  background: var(--kf-surface);
}
.kf-body textarea{ min-height: 100px; resize: vertical; }

/* Buttons — Luxury standard: pill-shaped, uppercase, letter-spaced gold,
   shared by every staff/admin page through this one file. */
.kf-btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: none;
  border-radius: var(--kf-radius-pill);
  padding: 12px 20px;
  font-family: var(--kf-font-body);
  font-weight: 700;
  font-size: .82rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  background: var(--kf-gold-soft);
  color: var(--kf-ocean-deep);
  transition: background .15s ease, transform .1s ease, box-shadow .15s ease;
}
@media (hover: hover) and (pointer: fine){ .kf-btn:hover{ background: var(--kf-gold); transform: translateY(-1px); box-shadow: var(--kf-shadow-sm); } }
.kf-btn:active{ transform: translateY(0); }
.kf-btn-block{ width: 100%; margin-top: 6px; }
.kf-btn-primary{ background: var(--kf-gold); }
@media (hover: hover) and (pointer: fine){ .kf-btn-primary:hover{ background: var(--kf-ocean); color: var(--kf-parchment); } }
.kf-btn-ghost{
  background: transparent;
  border: 1px solid var(--kf-line);
  color: var(--kf-ink);
}
@media (hover: hover) and (pointer: fine){ .kf-btn-ghost:hover{ background: var(--kf-surface-soft); } }
.kf-btn-danger{ background: var(--kf-late-bg); color: var(--kf-late); }
@media (hover: hover) and (pointer: fine){ .kf-btn-danger:hover{ background: var(--kf-late); color: #fff; } }
.kf-btn-success{ background: var(--kf-ok-bg); color: var(--kf-ok); }
@media (hover: hover) and (pointer: fine){ .kf-btn-success:hover{ background: var(--kf-ok); color: #fff; } }
.kf-btn-sm{ padding: 8px 14px; font-size: .68rem; border-radius: var(--kf-radius-pill); }

/* Messages / alerts */
.kf-msg{
  margin-top: 14px;
  font-size: .85rem;
  padding: 11px 13px;
  border-radius: var(--kf-radius-sm);
  line-height: 1.5;
}
.kf-msg-ok{ background: var(--kf-ok-bg); color: var(--kf-ok); }
.kf-msg-warn{ background: var(--kf-warn-bg); color: var(--kf-warn); }
.kf-msg-err{ background: var(--kf-late-bg); color: var(--kf-late); }
.kf-msg-neutral{ background: var(--kf-parchment-deep); color: var(--kf-ink-soft); }

/* Priority / toggle chip group (submit form) */
.kf-chip-row{ display: flex; gap: 8px; }
.kf-chip-row label{
  flex: 1; text-align: center;
  border: 1px solid var(--kf-line); border-radius: var(--kf-radius-sm);
  padding: 10px 4px; margin: 0;
  cursor: pointer; font-weight: 600; font-size: .85rem;
  transition: border-color .15s ease, background .15s ease;
}
.kf-chip-row input{ display: none; }
.kf-chip-row label:has(input:checked),
.kf-chip-row label.is-checked{ border-color: var(--kf-gold); background: var(--kf-gold-wash); }

/* ---------------- Tables ---------------- */
.kf-table-wrap{
  width: calc(100% + 64px);
  margin-left: -32px;
  margin-right: -32px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: 0;
  border: 1px solid var(--kf-line);
  border-left: none;
  border-right: none;
  background: var(--kf-surface);
  box-shadow: var(--kf-shadow-sm);
  scrollbar-width: none;
}
.kf-table-wrap::-webkit-scrollbar{ display: none; }
/* min-width was 980px, which is BELOW the width the columns actually need —
   so it never constrained anything and the table simply grew past it and
   scrolled. It is now the real floor for the reduced 8-column layout, so a
   narrow window shrinks the flexible Details column instead of pushing
   Actions off the right-hand edge. */
.kf-table{ width: 100%; min-width: 1180px; border-collapse: collapse; }
.kf-table th, .kf-table td{
  padding: 13px 12px;
  text-align: left;
  border-bottom: 1px solid var(--kf-line-soft);
  font-size: .95rem;
  vertical-align: top;
}
.kf-table th{
  background: var(--kf-parchment-deep);
  font-weight: 700;
  color: var(--kf-ink-soft);
  text-transform: uppercase;
  letter-spacing: .03em;
  font-size: .8rem;
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 700;
  box-shadow: 0 1px 0 var(--kf-line);
}
.kf-table tr:last-child td{ border-bottom: none; }
i.ti{ font-size: 1.3rem !important; vertical-align: -4px; }
@media (hover: hover) and (pointer: fine){
  .kf-table tr:hover td{ background: var(--kf-gold-wash); }
}

/* Status pills */
.kf-status{
  padding: 4px 10px;
  border-radius: var(--kf-radius-pill);
  font-size: .74rem;
  font-weight: 700;
  display: inline-block;
  white-space: nowrap;
}
.kf-status-open{ background: var(--kf-late-bg); color: var(--kf-late); }
.kf-status-followed_up{ background: var(--kf-warn-bg); color: var(--kf-warn); }
.kf-status-resolved{ background: var(--kf-ok-bg); color: #3E7A5C; }
.kf-priority-badge{
  display: inline-block; padding: 2px 9px; border-radius: var(--kf-radius-pill);
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .02em;
  margin-left: 6px;
}
.kf-priority-critical{ background: var(--kf-late-bg); color: var(--kf-late); }
.kf-priority-urgent{ background: var(--kf-warn-bg); color: var(--kf-warn); }
.kf-priority-standard{ background: var(--kf-ok-bg); color: #3E7A5C; }

/* ═══ Luxury toggle buttons — Complaint/Request, Standard/Urgent/Critical ═══ */
.priority{ display:flex; gap:10px; flex-wrap:wrap; }
.priority label{
  position: relative;
  flex: 1; min-width: 96px; text-align: center;
  border: 1px solid var(--kf-line); border-radius: var(--kf-radius-pill);
  padding: 12px 16px; margin: 0; cursor: pointer;
  background: var(--kf-surface);
  font-family: var(--kf-font-body); font-weight: 600; font-size: .85rem;
  letter-spacing: .03em;
  white-space: nowrap;
  color: var(--kf-ink-soft);
  transition: border-color .2s ease, background .2s ease, color .2s ease, box-shadow .2s ease, transform .15s ease;
}
@media (hover: hover) and (pointer: fine){ .priority label:hover{ border-color: var(--kf-gold-soft); color: var(--kf-ink); transform: translateY(-1px); } }
.priority input{
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
/* :has() support only reached Firefox in Dec 2023 and is still missing on
   many older/budget Android WebViews. .is-checked is a JS-driven fallback
   (see the small script on each page using .priority) so the selected
   button is still visually obvious even without :has() support — the
   :has() rules below are redundant-but-harmless on browsers that do
   support it. */
.priority label:has(input:checked),
.priority label.is-checked{
  border-color: var(--kf-gold);
  background: linear-gradient(180deg, var(--kf-gold-wash), var(--kf-gold-wash));
  color: var(--kf-ink);
  box-shadow: 0 0 0 1px var(--kf-gold), 0 6px 16px -6px rgba(201,161,90,.55);
  transform: translateY(-1px);
}
.priority input:checked + span{ font-weight: 700; }
.priority label:has(input:checked) span::before,
.priority label.is-checked span::before{
  content: "✓"; display: inline-block; margin-right: 6px; font-size: .8em; color: var(--kf-gold);
}
/* Priority-specific accent on selection — same colors as the badges elsewhere. */
.priority label:has(input[value="critical"]:checked),
.priority label.is-checked-critical{
  border-color: var(--kf-late); background: var(--kf-late-bg);
  box-shadow: 0 0 0 1px var(--kf-late), 0 6px 16px -6px rgba(208,135,112,.55);
}
.priority label:has(input[value="critical"]:checked) span::before,
.priority label.is-checked-critical span::before{ color: var(--kf-late); }
.priority label:has(input[value="urgent"]:checked),
.priority label.is-checked-urgent{
  border-color: var(--kf-warn); background: var(--kf-warn-bg);
  box-shadow: 0 0 0 1px var(--kf-warn), 0 6px 16px -6px rgba(214,161,90,.55);
}
.priority label:has(input[value="urgent"]:checked) span::before,
.priority label.is-checked-urgent span::before{ color: var(--kf-warn); }
.priority label:has(input[value="standard"]:checked),
.priority label.is-checked-standard{
  border-color: #3E7A5C; background: var(--kf-ok-bg);
  box-shadow: 0 0 0 1px #3E7A5C, 0 6px 16px -6px rgba(62,122,92,.45);
}
.priority label:has(input[value="standard"]:checked) span::before,
.priority label.is-checked-standard span::before{ color: #3E7A5C; }

/* ── Icon slot reservation ────────────────────────────────────────────────
   The Tabler icon stylesheet is loaded asynchronously (media="print" swapped
   to "all" on load) so it cannot block first paint — see the <head> of any
   page. The trade-off is that icons arrive a moment after the text, and
   without a reserved slot every one of them would shove the layout sideways
   as it lands. A fixed inline-block width means the space is already correct
   before the font arrives. Tabler sets the glyph via ::before, which this
   does not interfere with. */
.ti{
  display: inline-block;
  width: 1em;
  height: 1em;
  line-height: 1;
  text-align: center;
  flex-shrink: 0;
}

/* ── Forward-to-department dialog ─────────────────────────────────────── */
.kf-modal-label{
  display: block; margin: 14px 0 6px;
  font-size: .78rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--kf-ink-soft);
}
.kf-modal-label:first-of-type{ margin-top: 4px; }
.kf-modal-select{
  width: 100%; padding: 11px 13px; min-height: 44px;
  border: 1px solid var(--kf-line); border-radius: var(--kf-radius-sm, 8px);
  background: var(--kf-surface); color: var(--kf-ink);
  font-family: inherit; font-size: .95rem;
}
.kf-modal-select:focus{ outline: none; border-color: var(--kf-gold); }
.kf-modal-warn{ margin: 10px 0 0; font-size: .8rem; color: var(--kf-warn, #B4553F); }

/* ── Forwarded ticket, in the Status column ───────────────────────────────
   The badge sits right beside the status pill, because the first question
   anyone asks about a ticket in their queue is "why is this mine?". */
.kf-forwarded-badge{
  display: inline-block; margin-left: 6px; vertical-align: middle;
  padding: 3px 9px; border-radius: var(--kf-radius-pill);
  border: 1px solid var(--kf-gold); background: var(--kf-gold-wash);
  color: var(--kf-gold);
  font-size: .68rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; white-space: nowrap;
}
.kf-note-forwarded{ color: var(--kf-ink-soft); font-style: normal; }
.kf-fwd-route{ font-weight: 700; color: var(--kf-gold); white-space: nowrap; }
.kf-fwd-reason{ font-style: italic; }

/* ── Dashboard row cap ────────────────────────────────────────────────────
   Deliberately prominent: a truncated list that looks complete is worse
   than a slow one. */
.kf-row-cap{
  margin: 0 0 14px; padding: 10px 14px;
  border: 1px solid var(--kf-gold); border-left-width: 3px;
  border-radius: var(--kf-radius-sm, 8px);
  background: var(--kf-gold-wash);
  color: var(--kf-ink); font-size: .85rem; line-height: 1.5;
}

/* ── Group badge (dashboard) ──────────────────────────────────────────────
   Marks a ticket as one of several raised from a single guest report, so a
   department can see somebody else is already on the rest of it. */
.kf-group-badge{
  display: inline-block; margin-left: 6px;
  padding: 2px 8px; border-radius: var(--kf-radius-pill);
  border: 1px solid var(--kf-line);
  background: var(--kf-gold-wash);
  color: var(--kf-gold);
  font-size: .7rem; font-weight: 700; letter-spacing: .04em;
  white-space: nowrap; vertical-align: middle;
}
.kf-group-note{
  margin-top: 4px; font-size: .75rem; color: var(--kf-ink-faint);
  font-style: italic; line-height: 1.35; white-space: normal;
}
.kf-status-note{
  margin-top: 3px; font-size: .8rem; color: var(--kf-ink-soft); font-style: italic;
  max-width: 340px; line-height: 1.4;
}
/* ═══ Dashboard table column sizing ═══════════════════════════════════════
   The table had NO column widths at all. The browser auto-sized it, the
   Status column claimed 320-360px, the Details cell carried inline min/max
   widths in the markup, and the total blew past the (too low) 980px table
   minimum — so the wrapper scrolled sideways and the Actions column fell off
   the right-hand edge, while "24 Aug, 18:38" was squeezed onto three lines.

   There are two layouts, and the widths below were chosen by adding them up
   against real desktop widths rather than by eye:

     9 columns  1493px  -> fits 1536px and wider
     8 columns  1313px  -> fits 1366px and wider  (the common laptop)

   The PRIORITY COLUMN IS NEVER SHOWN. It is not hidden to save space — it
   was pure duplication, because the priority already renders as a badge
   inside the Status column right next to the status pill.

   Below 1536px the Type column also drops out, and the type appears as a
   small label under the ticket number instead (.kf-type-inline), so nothing
   is lost there either.

   Below 768px the layout switches to cards and none of this applies. */
.kf-table th, .kf-table td{ padding: 12px 9px; }

.kf-col-id{      width: 128px; }
.kf-col-type{    width:  96px; white-space: nowrap; }
.kf-col-guest{   width: 142px; }
.kf-col-dept{    width: 128px; }
.kf-col-tier{    width: 140px; }
.kf-col-prio{    display: none; }      /* duplicated by the badge in Status */
.kf-col-details{ min-width: 200px; }   /* the one column that absorbs slack */
.kf-col-raised{  width: 104px; white-space: nowrap; }  /* never wrap a short date */
.kf-col-raised .kf-date-link{ white-space: nowrap; }

.kf-col-status{
  width: 245px;
  white-space: normal !important; /* let notes wrap instead of forcing the column wider than needed */
}
.kf-col-status .kf-status,
.kf-col-status .kf-priority-badge,
.kf-col-status .kf-forwarded-badge{
  white-space: nowrap;
}

/* Stands in for the Type column once it is hidden. */
.kf-type-inline{ display: none; }

@media (min-width: 769px) and (max-width: 1535px){
  .kf-col-type{ display: none; }
  .kf-type-inline{
    display: inline-block; margin-top: 4px;
    font-size: .7rem; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--kf-ink-faint);
  }
  .kf-table th, .kf-table td{ padding: 11px 8px; font-size: .9rem; }
  .kf-col-id{      width: 124px; }
  .kf-col-guest{   width: 138px; }
  .kf-col-dept{    width: 118px; }
  .kf-col-tier{    width: 132px; }
  .kf-col-status{  width: 235px; }
  .kf-col-details{ min-width: 190px; }
  .kf-col-raised{  width: 104px; }
}

/* ═══ In-page toast notifications (slide in while the tab is open) ═══ */
.kf-toast-stack{
  position: fixed; left: 0; right: 0; bottom: 18px; z-index: 970;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  pointer-events: none; padding: 0 16px;
}
.kf-toast{
  pointer-events: auto;
  width: 100%; max-width: 380px;
  background: var(--kf-parchment-deep); border: 1px solid var(--kf-line);
  border-left: 3px solid var(--kf-gold);
  border-radius: var(--kf-radius); box-shadow: var(--kf-shadow-lg, 0 20px 50px rgba(0,0,0,.4));
  padding: 12px 14px; display: flex; align-items: flex-start; gap: 10px;
  text-decoration: none !important; color: inherit;
  transform: translateY(24px); opacity: 0;
  transition: transform .28s cubic-bezier(.2,.8,.2,1), opacity .28s ease;
}
.kf-toast.is-in{ transform: translateY(0); opacity: 1; }
.kf-toast-icon{ color: var(--kf-gold); font-size: 18px; flex-shrink: 0; margin-top: 1px; }
.kf-toast-body{ flex: 1; min-width: 0; }
.kf-toast-title{ font-size: .85rem; font-weight: 700; color: var(--kf-ink); margin-bottom: 2px; }
.kf-toast-detail{ font-size: .8rem; color: var(--kf-ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kf-toast-close{
  flex-shrink: 0; background: none; border: none; color: var(--kf-ink-faint); cursor: pointer;
  font-size: 16px; line-height: 1; padding: 2px;
}
@media (hover: hover) and (pointer: fine){ .kf-toast-close:hover{ color: var(--kf-ink); } }

/* ═══ Reusable confirm-with-note modal (status changes, etc.) ═══ */
.kf-modal-overlay{
  position: fixed; inset: 0; z-index: 960; background: rgba(0,0,0,.45);
  display: none; align-items: center; justify-content: center; padding: 20px;
}
.kf-modal-overlay.is-open{ display: flex; }
.kf-modal{
  background: var(--kf-surface); border: 1px solid var(--kf-line); border-radius: var(--kf-radius-lg);
  box-shadow: var(--kf-shadow-lg, 0 24px 64px rgba(0,0,0,.55));
  padding: 22px; width: 100%; max-width: 420px;
}
.kf-modal h3{ font-family: var(--kf-font-display); font-size: 1.15rem; margin-bottom: 6px; color: var(--kf-ink); }
.kf-modal-sub{ font-size: .82rem; color: var(--kf-ink-soft); margin-bottom: 14px; }
.kf-modal textarea{ width: 100%; resize: vertical; min-height: 70px; }
.kf-modal-actions{ display: flex; justify-content: flex-end; gap: 10px; margin-top: 14px; }

/* Ticket confirmation panel */
.kf-panel{
  margin-top: 26px;
  padding: 22px;
  background: var(--kf-surface);
  border: 1px solid var(--kf-line);
  border-radius: var(--kf-radius);
  box-shadow: var(--kf-shadow-sm);
}
.kf-ticket-id{ font-family: var(--kf-font-display); font-size: 1.35rem; color: var(--kf-gold); }

.kf-escalation{ margin-top: 18px; border-left: 2px solid var(--kf-line); padding-left: 18px; }
.kf-tier{ position: relative; padding-bottom: 20px; }
.kf-tier:last-child{ padding-bottom: 0; }
.kf-tier::before{
  content: ''; position: absolute; left: -23px; top: 3px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--kf-line); border: 2px solid var(--kf-surface);
}
.kf-tier.is-active::before{ background: var(--kf-warn); }
.kf-tier.is-done::before{ background: var(--kf-ok); }
.kf-tier h4{ margin: 0 0 3px; font-size: .9rem; font-weight: 700; }
.kf-tier p{ margin: 0; color: var(--kf-ink-soft); font-size: .82rem; }
.kf-tier .kf-sla{ font-size: .75rem; color: var(--kf-gold); font-weight: 600; margin-top: 2px; }

/* Foot notes */
.kf-footnote{
  margin-top: 34px; font-size: .78rem; color: var(--kf-ink-soft);
  border-top: 1px dashed var(--kf-line); padding-top: 16px;
}

@media (max-width: 520px){
  .kf-chip-row{ flex-direction: column; }
}

@media (max-width: 520px){
  .kf-btn{ flex: 1 1 auto; white-space: nowrap; text-align: center; }
}

/* ═══════════════════════════════════════════════════════════════════
   MOBILE PASS — most guests/staff are on a phone, so touch targets and
   the wide staff/admin tables need real adaptation here, not just
   reflowing text. Scoped to this breakpoint so the desktop staff
   console (designed pixel-precisely) is untouched.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 768px){
  /* Icon buttons (bell, theme toggle, drawer burger) were 30×30px —
     under Apple/Google's ~44px minimum recommended touch target, and
     these are exactly the controls tapped most often. Grow the hit
     area without visually enlarging the icon much. */
  .kf-icon-btn{ width: 44px; height: 44px; }
  .kf-icon-btn i.ti{ font-size: 19px !important; }
  .kf-burger{ padding: 10px; }

  /* Small action buttons (table row actions like "Followed up" /
     "Resolved") were ~28px tall — grow to a comfortable tap height. */
  .kf-btn-sm{ padding: 11px 14px; font-size: .82rem; min-height: 40px; }

  /* Top bar: tighten side padding and let the back-link's label shrink
     before it fights the logo/icons for space on a narrow screen. */
  .kf-topbar{ padding: 12px 14px; }
  .kf-nav-back{ font-size: 12px; letter-spacing: .08em; }
  .kf-main{ padding: 20px 16px 72px; }

  /* Wide data tables (tickets, users, activity log, guest check-ins):
     a 980px-min-width table forced horizontal scrolling on every phone.
     Below this width, each row becomes its own card instead — every
     cell's data-label attribute supplies the field name that the
     (now-hidden) column header used to provide. */
  .kf-table-wrap{
    width: auto; margin-left: 0; margin-right: 0;
    overflow-x: visible; overflow-y: visible; max-height: none;
    touch-action: auto; overscroll-behavior: auto; -webkit-overflow-scrolling: auto;
    border-radius: var(--kf-radius);
    border: 1px solid var(--kf-line);
  }
  .kf-table{ min-width: 0; width: 100%; }
  .kf-table tr:first-child{ display: none; } /* the plain header row */
  .kf-table tr{
    display: block;
    padding: 11px 14px;
    border-bottom: 7px solid var(--kf-parchment);
  }
  .kf-table tr:last-child{ border-bottom: none; }
  .kf-table td{
    display: block;
    border-bottom: none;
    padding: 4px 0;
    font-size: .85rem;
    line-height: 1.3;
  }
  .kf-table td[data-label]::before{
    content: attr(data-label);
    display: block;
    font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--kf-ink-faint); margin-bottom: 1px;
  }
  .kf-table td{ overflow-wrap: break-word; word-break: break-word; }
  .kf-table td:last-child{ padding-top: 8px; display: flex; flex-wrap: wrap; gap: 7px; }
  .kf-table td:last-child .kf-btn{ flex: 1 1 auto; padding: 9px 12px; font-size: .8rem; }
  .kf-col-status{ min-width: 0; }

  /* Ticket dashboard specifically: a compact 2-column card instead of 11
     stacked full-width blocks (that stacked version was the actual
     complaint — too tall, too much scrolling per ticket). Short fields
     pair up side by side; only genuinely long content (guest/room,
     details, status, actions) takes the full row. No HTML changes needed
     — this is pure grid placement over the same cells the desktop table
     already has, scoped ONLY to this table since column order is
     specific to it (other tables like Users/Log/Guests keep the simpler
     one-per-row treatment above, since their columns mean different
     things at each position). */
  .kf-table-tickets tr{
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 12px;
    row-gap: 5px;
  }
  .kf-table-tickets td{ padding: 0; }
  /* No 'order' property here on purpose. It previously moved Raised (DOM
     position 9) to appear before Details (DOM position 7) — a genuine
     backward reorder. Some WebKit/Safari versions place CSS Grid items
     unreliably when 'order' reorders them out of DOM sequence, producing
     large phantom empty rows (confirmed: this exact ticket rendered with
     zero gaps in Chromium testing, but showed large gaps on an actual
     iPhone). Keeping every field in natural DOM order removes the need
     for any reordering at all, so there's nothing for any browser to get
     wrong — Priority and Raised each just get their own row instead of
     being paired together; costs a little vertical space, but renders
     identically everywhere. */
  .kf-table-tickets td:nth-child(1){ font-size: .95rem; font-weight: 700; }  /* Ticket # */
  .kf-table-tickets td:nth-child(3){ grid-column: 1 / -1; }                 /* Guest/Room */
  .kf-table-tickets td:nth-child(7){ grid-column: 1 / -1; }                 /* Details */
  .kf-table-tickets td:nth-child(8){ grid-column: 1 / -1; }                 /* Status (includes Opened by / Follow-up / Resolved) */
  .kf-table-tickets td:nth-child(10){ grid-column: 1 / -1; }                /* Actions */
  .kf-table-tickets td:last-child{ padding-top: 4px; }

  /* Manage Users: Name (full width, bold) → Username + Role paired →
     Department + Tier paired → Notify email + Created paired → Actions
     full width. Same 2-up grid technique as the tickets table above. */
  .kf-table-users tr{ display: grid; grid-template-columns: 1fr 1fr; column-gap: 12px; row-gap: 8px; }
  .kf-table-users td{ padding: 0; }
  /* No 'order' property — see the note above the tickets table for why.
     Fields pair with whichever field is already next to them in the HTML,
     so nothing needs reordering: Username+Notify email, Role+Department,
     Tier+Created. */
  .kf-table-users td:nth-child(1){ grid-column: 1 / -1; font-size: .95rem; font-weight: 700; } /* Name */
  .kf-table-users td:nth-child(8){ grid-column: 1 / -1; padding-top: 4px; } /* Actions */

  /* The EDIT row is a different shape: 6 cells, not 8, because Department,
     Tier and Created collapse into one tall colspan cell. nth-child(8)
     therefore never matched it, so its Save cell sat in a narrow column
     beside that tall cell — and since grid items stretch by default, and
     td:last-child is a flex row whose .kf-btn is flex:1 1 auto, the Save
     button was stretched to the full height of the whole department
     block. That was the giant vertical pill.

     Both fixes are needed: full width so it isn't squeezed beside a tall
     neighbour, and start-alignment so it can never be stretched by one
     again whatever the row's shape. Targeting last-child rather than a
     position number means this holds for BOTH row shapes, and for any
     future column added to either. */
  .kf-table-users td:last-child{
    grid-column: 1 / -1;
    align-self: start;
    padding-top: 4px;
  }
  .kf-table-users .editDeptRow{ grid-column: 1 / -1; }

  /* Buttons keep their natural height inside these stacked action cells. */
  .kf-table td:last-child{ align-items: center; }
  .kf-table td:last-child .kf-btn,
  .kf-table td:last-child button{ align-self: center; }

  /* Guest Check-ins: Room + Name paired → Departure + Checked in paired
     → Actions full width. */
  .kf-table-guests tr{ display: grid; grid-template-columns: 1fr 1fr; column-gap: 12px; row-gap: 8px; }
  .kf-table-guests td{ padding: 0; }
  .kf-table-guests td:nth-child(1){ font-size: .95rem; font-weight: 700; } /* Room / Villa */
  .kf-table-guests td:nth-child(5){ grid-column: 1 / -1; padding-top: 4px; } /* Actions */

  /* Manage Menus: Title + Status paired → Actions full width. */
  .kf-table-menus tr{ display: grid; grid-template-columns: 1fr 1fr; column-gap: 12px; row-gap: 8px; align-items: center; }
  .kf-table-menus td{ padding: 0; }
  .kf-table-menus td:nth-child(1){ font-size: .95rem; font-weight: 700; } /* Title */
  .kf-table-menus td:nth-child(3){ grid-column: 1 / -1; padding-top: 4px; } /* Actions */
}

/* ═══ PAGE-TO-PAGE MOVEMENT ═══════════════════════════════════════════════
   Every screen here is its own PHP file, so moving between them is a real
   page load. None of this fakes that away — it stops the load from looking
   like the app froze, which is what it felt like on a phone.
   ════════════════════════════════════════════════════════════════════════ */

/* Cross-document view transitions: the browser holds the page you're
   leaving on screen and cross-fades into the new one, rather than showing
   the blank gap in between. Browsers without support just navigate as
   they always did — nothing here is required for the site to work. */
@view-transition{ navigation: auto; }
::view-transition-old(root){ animation: kfPageOut .13s ease-out both; }
::view-transition-new(root){ animation: kfPageIn .22s cubic-bezier(.22,1,.36,1) both; }
@keyframes kfPageOut{ from{ opacity: 1; } to{ opacity: 0; } }
@keyframes kfPageIn{ from{ opacity: 0; transform: translateY(8px); } to{ opacity: 1; transform: none; } }

/* Thin loading line along the top edge, shown the moment a link is tapped
   (see assets/js/theme.js), so a slow connection never leaves someone
   staring at a screen that looks like it ignored the tap. */
#kfProgress{
  position: fixed; top: 0; left: 0; height: 2px; width: 0;
  background: linear-gradient(90deg, var(--kf-gold-soft, #b89b89), var(--kf-gold, #d1b4a1));
  z-index: 1000; opacity: 0; pointer-events: none;
  transition: width .6s cubic-bezier(.1,.8,.2,1), opacity .2s ease;
}
#kfProgress.is-on{ opacity: 1; }
.is-navigating{ opacity: .5; transition: opacity .12s ease; }

/* On a touch screen there's no pointer to move away, so :hover latches on
   after a tap and stays latched — the row you tapped is still highlighted
   when you come back to the page. Real presses are acknowledged with
   :active instead, which releases properly. */
@media (hover: none){
  .kf-table tr:active td{ background: var(--kf-gold-wash); }
  .drawer-link:active{ background: var(--kf-gold-wash); }
}

@media (prefers-reduced-motion: reduce){
  ::view-transition-old(root), ::view-transition-new(root){ animation: none; }
  #kfProgress{ transition: none; }
}

/* ── Instant press feedback (kf-press.js) ─────────────────────────────────
   A form post reloads the whole page, and on a slow connection nothing on
   screen changes while that happens — so a button looks stuck and gets
   pressed again. These styles are what the person sees the moment they
   press, before the server has answered. */
.kf-is-busy{
  opacity: .72;
  pointer-events: none;          /* the press registered; ignore the rest */
  cursor: progress;
  position: relative;
}
.kf-press-spin{
  display: inline-block;
  width: 12px; height: 12px;
  margin-right: 7px;
  vertical-align: -1px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: kf-press-spin .6s linear infinite;
}
@keyframes kf-press-spin{ to{ transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce){
  .kf-press-spin{ animation: none; opacity: .6; }
}

/* A tapped menu row on the guest site, while its PDF loads. */
.kf-is-pressed{
  opacity: .6;
  transition: opacity .12s ease;
}

/* Give every button and menu row an immediate touch response, so a tap is
   acknowledged even before any JavaScript runs. */
.kf-btn:active,
.ml-row:active,
.kf-menu-row:active{ transform: scale(.985); }
