/* Sentinel — kf-mobile.js reads this to confirm THIS file actually loaded.
   If the build badge says "CSS MISSING", this stylesheet never reached the
   device, and no styling change can possibly appear however many times the
   JavaScript is uploaded. */
:root { --kf-mobile-css: 1; }

/* kf-mobile.css — the mobile redesign.
 *
 * EVERYTHING HERE IS INSIDE @media (max-width: 768px).
 * The desktop site is untouched: same top bar, same drawer, same layout.
 * Below 768px the top bar and drawer are hidden and replaced by floating
 * glass controls and a pill tab bar, built by kf-mobile.js.
 *
 * WHY 768px: it is the breakpoint theme.css already uses to stack tables,
 * so the whole site changes shape at one width instead of two.
 */

/* ══════════════════════════════════════════════════════════════════════
   ONE DESIGN, TWO WIDTHS.
   This used to be wrapped in @media (max-width: 768px) so it applied to
   phones only, which meant desktop kept the old top bar and drawer — two
   designs to build, two to debug, and they drifted apart. Everything here
   now applies at EVERY width, and the handful of genuine desktop
   differences are added at the end: the pill gets text labels, the cards
   lay out in columns.
   ══════════════════════════════════════════════════════════════════════ */
@media all {

  /* ── Out with the bars ───────────────────────────────────────────────
     The top bar and the drawer are hidden, not deleted. kf-mobile.js reads
     the drawer's links to build the tab bar and the More sheet, so a link
     the server did not render (no permission) can never appear in the bar
     either. That is why this is done from the live DOM rather than a fixed
     list — permissions stay correct for free. */
  /* The staff pages use .kf-topbar / .kf-drawer. The GUEST pages use a bare
     <nav id="mainNav"> with .nav-right, .theme-toggle and .burger inside, and
     a .sticky-book tab down the side. The first version of this file only
     listed the staff class names, so on a guest page the old bar stayed on
     screen and its theme toggle sat underneath the new floating one — two
     overlapping circles in the corner. Both sets are named here now. */
  .kf-topbar,
  .kf-drawer,
  .kf-drawer-overlay,
  .kf-burger,
  .topbar,
  .drawer,
  .drawer-overlay,
  .burger,
  nav#mainNav,
  .nav-right,
  .nav-back,
  .nav-logo,
  .theme-toggle,
  .sticky-book { display: none !important; }

  body.kf-body,
  body { padding-top: 0 !important; }

  /* Room for the floating bar so the last card is never trapped under it. */
  .kf-main,
  main { padding-bottom: 124px !important; max-width: 100% !important; }

  /* ONE clearance value for both portals.
     The bar itself is identical on guest and staff — measured at top 756,
     height 66, gap 22 below, on every page of both. What differed was the
     space left ABOVE it: staff had 124px, guest only 96px. So on guest the
     last thing on the page sat closer to the bar, which reads as the bar
     being higher even though it is in exactly the same place. */
  /* The bar clearance moved to .kf-m-scroll — keeping it here as well would
     leave a screenful of blank at the end of every page. */
  .kf-main, main, .site-footer { padding-bottom: 0 !important; }

  /* THE BAR THAT WOULD NOT STAY PUT.
   *
   * theme.css sets `html { overflow-x: hidden; overflow-x: clip }`, and I had
   * added `body { overflow-x: hidden }` on top of it. On iOS that combination
   * breaks position:fixed — the element stops being fixed to the screen and
   * scrolls with the page instead. That is why the bar sat high on a short
   * page like De' North and low on a long one like the home screen: it was
   * following the content, not the viewport.
   *
   * Both are released here. Sideways scrolling is held back by max-width on
   * the content instead, which does not affect positioning. */
  html, body, body.kf-body {
    overflow-x: visible !important;

    /* -webkit-overflow-scrolling: touch on the BODY is the other half of it.
       It hands the page to a separate momentum-scrolling layer, and inside
       that layer iOS does not keep position:fixed elements pinned — they
       drift with the content. theme.css sets it on body.kf-body. In Safari
       the effect is masked because the toolbar resize forces a repaint every
       time; added to the home screen there is no toolbar, nothing forces the
       repaint, and the bar simply lands wherever the last scroll left it.
       That is the jumping in your recording, and why Safari looked fine. */
    -webkit-overflow-scrolling: auto !important;

    /* 100vh is taller than the visible area on iOS, which pushes the bottom
       of the page past the screen and moves anything measured from it. */
    min-height: 100% !important;

    /* RUBBER-BANDING. This is the one that matches what your video shows.
     *
     * When you drag past the top or bottom of a page, iOS lets the whole
     * document bounce. During that bounce it moves position:fixed elements
     * WITH the page — so the bar slides down and off the screen on an upward
     * drag, then comes back. It is not the bar losing its position; it is the
     * page being dragged out from under it.
     *
     * theme.css leaves overscroll-behavior at auto, which permits the bounce.
     * Turning it off on the page means the drag stops at the edge and the bar
     * has nothing to follow. The bar keeps its own bounce — that is set on
     * the bar itself, so it can still be flicked sideways. */
    overscroll-behavior: none !important;
    overscroll-behavior-y: none !important;
  }
  @supports (min-height: 100dvh) {
    body, body.kf-body { min-height: 100dvh !important; }
  }

  /* Nothing between the bar and the viewport may create a containing block
     for it — a transform, filter or clip on any ancestor silently turns
     position:fixed into position:absolute. */
  body > .kf-m-tabbar,
  body > .kf-m-fabs {
    position: fixed !important;
    will-change: auto !important;
  }
  .kf-main, main, .kf-lede, .kf-sub, .kf-panel, .kf-card {
    overflow-wrap: break-word;
    word-wrap: break-word;
  }
  .kf-lede, .kf-sub, .kf-main p, main p {
    white-space: normal !important;
    overflow-wrap: break-word !important;
    max-width: 100% !important;
  }
  .kf-main *, main * { max-width: 100%; }
  /* This one is set to white-space:nowrap in theme.css, so the dashboard's
     "Showing today's tickets..." line ran off the right edge on a phone
     instead of wrapping onto a second line. */
  .kf-filter-summary { white-space: normal !important; display: block !important; }
  .kf-main table, main table { display: block; overflow-x: auto; }

  /* ── The shell that holds the bar and the circles ──────────────────────
     Sized with 100dvh — the viewport you can actually SEE. Anything
     positioned against it therefore sits against the real screen edge, not
     against iOS's taller "large viewport". It ignores taps so the page
     underneath stays usable; the bar and circles take their own back. */
  /* A vertical column that fills the screen: the scrolling box on top, the
     bar underneath it. Because the bar is a real row rather than something
     floating over the page, content CANNOT pass behind it and there is no
     strip left below it. */
  /* Holds the bar and the circles only. It does not contain the page, so it
     cannot stop the page reaching the bottom of the screen. */
  .kf-m-shell {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    pointer-events: none;
    z-index: 950;
  }
  .kf-m-shell > * { pointer-events: auto; }

  /* FULL SCREEN, corner to corner — the way Instagram does it.
     Docking the bar as a row reserved space for it, and that reserved strip
     is what kept showing as a band at the bottom. The box now fills the
     entire screen and the content runs all the way down behind the bar, so
     there is nothing left over to show. */


  /* The bar floats OVER the content, 22px off the bottom — Instagram's
     placement, measured off your screenshot. */
  .kf-m-shell > .kf-m-tabbar {
    position: fixed !important;
    left: 5%; right: 5%;
    bottom: 22px;
    width: auto;
  }
  .kf-m-shell .kf-m-fabs { position: absolute; }

  /* No theme switching anywhere — the button is removed from the script and
     any the page renders itself is hidden here. */
  .theme-toggle, #themeToggle { display: none !important; }   /* ours replaces it */


  /* ══════════════════════════════════════════════════════════════════════
     ONE SET OF TOKENS FOR BOTH SIDES
     The staff pages and the guest pages each carried their own colours,
     fonts and sizes, which is why they looked like two products. Everything
     below is forced to the same values on every page of both, so a change
     here changes both at once.
     ══════════════════════════════════════════════════════════════════════ */
  /* The font stacks are declared HERE, not inherited from theme.css.
     The guest pages were falling back to Georgia while the staff pages used
     Playfair Display, so the two sides literally had different lettering. */
  :root, html {
    --kf-font-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
    --kf-font-body: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  }

  :root,
  html[data-theme="light"],
  html:not([data-theme="dark"]) {
    --kf-paper:      #F5EEE3;
    --kf-surface:      #FFFFFF;
    --kf-surface-line: rgba(74,59,51,0.08);
    --kf-card:       #FFFFFF;
    --kf-ink:        #3A2F28;
    --kf-ink-soft:   #7A6A5A;
    --kf-ink-faint:  #BFAE99;
    --kf-gold:       #7D5E28;
    --kf-brown:      #8A7358;
    --kf-line:       rgba(74,59,51,0.07);
    --kf-bar:        #FBF6EE;
  }
  html[data-theme="dark"] {
    --kf-surface:      rgba(255,255,255,0.07);
    --kf-surface-line: rgba(255,255,255,0.13);
    --kf-paper:      #14100C;
    --kf-card:       rgba(255,255,255,0.07);
    --kf-ink:        #EFE4D5;
    --kf-ink-soft:   #A99B8C;
    --kf-ink-faint:  #8A7C6B;
    --kf-gold:       #E0C89A;
    --kf-brown:      #6E5539;
    --kf-line:       rgba(255,255,255,0.12);
    --kf-bar:        #201A14;
  }

  /* Same background and text colour on every page, both sides. */
  html, body, body.kf-body {
    background: var(--kf-paper) !important;
    color: var(--kf-ink) !important;
  }

  /* Same cards. The staff pages used their own panel styling. */
  /* ONE CARD, EVERYWHERE.
     Audited page by page and the cards genuinely differed: .ib was 18px and
     translucent white, .ml was 16px and solid, .kf-m-tile had a brown-tinted
     border, .kf-panel was translucent again. Four card styles across the two
     halves is exactly what makes it read as two websites even when the
     colours and fonts match.
     Every card surface in the app is listed here and given the same
     treatment, so there is one card and no exceptions. */
  .ib, .wx-card, .rmap-card, .kf-panel, .kf-card, .kf-m-tile:not(.is-dark),
  .kf-table-wrap, .kf-box, .kf-section, .ml, .lux-row, .pillar,
  .kf-m-quick-ico, .kf-m-stats, .kf-tile, .kf-row, .kf-list-item,
  .kf-form-card, .kf-filter-card, .kf-summary-card, .kf-ticket-card,
  form.kf-form > fieldset, .kf-admin-card, .kf-note,
  /* Found by auditing the pages my first pass reported as "no cards": the
     booking page uses .card at 14px and the minibar page .charge-notice at
     10px. Three more radii nobody would have guessed were there. */
  .card, .charge-notice, .notice, .info-box, .form-card, .panel, .fb-modal-body {
    /* ONE LIST, BOTH THEMES. The colour comes from a variable that each
       theme sets, so a card class added here is automatically correct in
       dark mode too. Previously this was hard #FFFFFF, and a SEPARATE dark
       list re-coloured cards — which nobody updated when .card,
       .charge-notice and the feedback modal were added here. In dark mode
       those three stayed white under cream text: 1.04 to 1.11 : 1, so the
       Laundry, MiniBar, Booking and Feedback forms were close to invisible. */
    background: var(--kf-surface) !important;
    border: 1px solid var(--kf-surface-line) !important;
    border-radius: 16px !important;
    box-shadow: none !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
  html[data-theme="dark"] .ib,
  html[data-theme="dark"] .wx-card,
  html[data-theme="dark"] .rmap-card,
  html[data-theme="dark"] .kf-panel,
  html[data-theme="dark"] .kf-card,
  html[data-theme="dark"] .kf-m-tile:not(.is-dark),
  html[data-theme="dark"] .kf-table-wrap,
  html[data-theme="dark"] .ml,
  html[data-theme="dark"] .lux-row,
  html[data-theme="dark"] .pillar,
  html[data-theme="dark"] .kf-m-quick-ico,
  html[data-theme="dark"] .kf-m-stats {
    background: rgba(255,255,255,0.07) !important;
    border-color: rgba(255,255,255,0.13) !important;
  }

  /* Same icon colour everywhere — staff icons were a different tone. */
  /* !important, because the staff pages tint their icons a different brown.
     That one difference is very visible side by side — it was the clearest
     sign of "two websites" after the layout was matched. */
  body .ti, body i.ti, html body [class*="ti-"],
  .kf-m-tile i, .kf-m-quick-ico i, .ml-ico i, .lux-icon i,
  .kf-icon-btn i, .drawer-link i {
    /* A deeper gold. The previous tone read as washed out against the pale
       background, especially at small sizes. */
    color: #7D5E28 !important;
  }
  html[data-theme="dark"] body .ti,
  html[data-theme="dark"] body i.ti { color: #E0C89A !important; }
  .kf-m-tab i.ti { color: inherit; }
  .kf-m-tile.is-dark i, .kf-m-tile.is-dark b, .kf-m-tile.is-dark span { color: #fff !important; }

  /* Same headings and body type. */
  h1, h2, h3, .ib-title, .kf-m-hi, .ih-title, .kf-m-tile b {
    font-family: 'Playfair Display', Georgia, 'Times New Roman', serif !important;
    color: var(--kf-ink) !important;
    font-weight: 400 !important;
  }
  body, p, li, td, th, label, input, select, textarea, button,
  .ml-label, .ml-desc, .kf-m-tile span, .kf-m-tab span, .kf-m-stats span {
    font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
  }

  /* Same buttons on both sides. */
  .kf-btn, button.kf-btn, .gold-pill, .bb, .cc {
    border-radius: 999px !important;
    font-size: 15px !important;
  }
  .kf-btn-primary, .kf-btn.kf-btn-primary { background: var(--kf-brown) !important; color: #fff !important; }

  /* Same table look — staff tables were the most different thing on the site. */
  /* THE HEADER ROW WAS BARELY THERE.
     It was drawn as rgba(28,20,16,0.4) — 40% opacity ink on a pale band,
     which composites to about rgb(156,150,144) and gives roughly 2.6:1
     against the background. The readable minimum for text this small is
     4.5:1, so the column names were genuinely below the threshold rather
     than merely subtle.
     Solid colour now, slightly larger, a touch heavier, on a band with a
     little more tone so the row reads as a header. */
  table th {
    font-size: 12.5px !important;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #5A4A3C !important;
    font-weight: 600 !important;
    background: #EDE3D4 !important;
    border-bottom: 1px solid rgba(74,59,51,0.14) !important;
    opacity: 1 !important;
  }
  table thead tr { background: #EDE3D4 !important; }
  html[data-theme="dark"] table th {
    color: #D8C9B4 !important;
    background: #221C15 !important;
    border-bottom-color: rgba(255,255,255,0.14) !important;
  }
  html[data-theme="dark"] table thead tr { background: #221C15 !important; }

  /* The card labels on mobile had the same washed-out treatment. */
  .kf-m-rowlabel { color: #6B5B4A !important; font-weight: 600 !important; }
  html[data-theme="dark"] .kf-m-rowlabel { color: #C9B9A2 !important; }
  table td { font-size: 15px !important; color: var(--kf-ink) !important; }
  table tr { border-bottom: 0.5px solid var(--kf-line) !important; }

  /* The nudge arrows at each end of the bar. Same glass finish, so they
     read as part of it rather than stuck on. */
  .kf-m-nudge {
    position: fixed;
    bottom: 22px;
    width: 34px; height: 60px;
    display: none; align-items: center; justify-content: center;
    border: 0.5px solid rgba(255,255,255,0.92);
    border-radius: 999px;
    background: rgba(251,246,238,0.94);
    -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
    box-shadow: 0 4px 18px rgba(74,59,51,0.18);
    cursor: pointer; z-index: 955; padding: 0;
  }
  .kf-m-nudge-l { left: calc(5% - 40px); }
  .kf-m-nudge-r { right: calc(5% - 40px); }

  /* TOUCH DEVICES NEVER SEE THESE.
     They exist so a mouse can move the bar; a finger already swipes it. I
     said they would be hidden on a phone and then never wrote the rule — so
     they sat half off each edge as two pale blobs, which is the "extra part"
     at the left and right of your toolbar. */
  @media (hover: none), (pointer: coarse) {
    .kf-m-nudge { display: none !important; }
  }
  .kf-m-nudge i { font-size: 18px !important; }
  [data-theme="dark"] .kf-m-nudge {
    background: rgba(32,26,20,0.94);
    border-color: rgba(255,255,255,0.14);
  }
  /* The bar itself shows a grab cursor on a desktop, so it is obvious it
     can be dragged. */
  @media (hover: hover) and (pointer: fine) {
    .kf-m-tabbar { cursor: grab; }
  }

  /* Seasonal decorations in the header. Static on purpose — no animation. */
  .kf-m-decor {
    position: absolute;
    top: 10px; left: 0; right: 0;
    text-align: center;
    font-size: 15px;
    letter-spacing: 14px;
    opacity: 0.85;
    pointer-events: none;
  }
  .inner-hero, .kf-m-hero-photo { position: relative; }

  /* ── Staff rows as cards ───────────────────────────────────────────────
     Matched to the Manage Departments card, which is the one staff page that
     already reads well on a phone: white, 22px corners, 18/22 padding, the
     label small and uppercase ABOVE the value rather than beside it. */
  .kf-m-tablehidden { display: none !important; }

  .kf-m-cards { display: block; }
  .kf-m-rowcard {
    background: #FFFFFF;
    border: 1px solid rgba(74,59,51,0.08);
    border-radius: 22px;
    padding: 18px 22px;
    margin-bottom: 16px;
  }
  .kf-m-rowline { padding: 9px 0; border-bottom: 1px solid rgba(74,59,51,0.06); }
  .kf-m-rowline:last-child { border-bottom: 0; padding-bottom: 0; }
  .kf-m-rowline:first-child { padding-top: 0; }
  .kf-m-rowlabel {
    display: block;
    font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
    color: #BFAE99; margin-bottom: 4px;
  }
  .kf-m-rowvalue { font-size: 16px; color: #3A2F28; line-height: 1.5; }
  /* A cell of buttons: they sit in a row and wrap, with room to tap. */
  .kf-m-rowline-act .kf-m-rowvalue {
    display: flex; flex-wrap: wrap; gap: 8px; padding-top: 4px;
  }
  .kf-m-rowline-act .kf-m-rowvalue > * { flex: 0 0 auto; }

  html[data-theme="dark"] .kf-m-rowcard {
    background: rgba(255,255,255,0.07);
    border-color: rgba(255,255,255,0.13);
  }
  html[data-theme="dark"] .kf-m-rowvalue { color: #EFE4D5; }
  html[data-theme="dark"] .kf-m-rowline { border-bottom-color: rgba(255,255,255,0.08); }

  /* The ticket a notification pointed at. A warm wash and a bar down the
     side, fading out after a few seconds — enough to say "this one" without
     leaving the page looking permanently altered. */
  .kf-m-highlight {
    animation: kf-m-flash 4s ease-out forwards;
    border-left: 3px solid #A8613C !important;
  }
  @keyframes kf-m-flash {
    0%   { background: #F6E3D5 !important; }
    12%  { background: #F6E3D5 !important; }
    100% { background: #FFFFFF !important; }
  }
  html[data-theme="dark"] .kf-m-highlight {
    animation: kf-m-flash-dark 4s ease-out forwards;
  }
  @keyframes kf-m-flash-dark {
    0%   { background: #3A2A1E !important; }
    12%  { background: #3A2A1E !important; }
    100% { background: rgba(255,255,255,0.07) !important; }
  }
  @media (prefers-reduced-motion: reduce) {
    .kf-m-highlight { animation: none; background: #F6E3D5 !important; }
  }

  /* ── SOFT PRESS ────────────────────────────────────────────────────────
     Nothing on screen acknowledged a tap. On island internet a page can take
     a second or two to answer, and in that gap the app looked frozen — so
     people press again, which sends the request twice.
     Everything tappable now dips very slightly under the finger and springs
     back. It is deliberately subtle: 3-4% of scale, not a bounce.
     touch-action: manipulation also removes the browser's 300ms wait for a
     possible double-tap, so every tap registers immediately. */
  .kf-m-tab, .kf-m-fab, .kf-m-tile, .kf-m-quick-item, .kf-m-rowcard,
  .ml, .lux-row, .pillar, .kf-btn, button, .bb, .cc, .gold-pill,
  a.kf-m-tab, .kf-m-nudge, .kf-m-bell-x, .card, .kf-card {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: transform .13s cubic-bezier(.3,.7,.4,1),
                opacity   .13s ease,
                background-color .13s ease;
  }

  /* !important on the pressed state: several of these already carry a
     transform of their own (the circles are positioned with one, the rows
     inherit one), and without it the press was simply ignored on them. */
  .kf-m-tab:active            { transform: scale(0.90) !important; }
  .kf-m-fab:active            { transform: scale(0.90) !important; }
  .kf-m-nudge:active,
  .kf-m-bell-x:active         { transform: scale(0.90) !important; }

  .kf-m-tile:active,
  .kf-m-quick-item:active,
  .kf-m-rowcard:active,
  .ml:active, .lux-row:active, .ib:active,
  .pillar:active, .card:active { transform: scale(0.975) !important; }

  button:active, .kf-btn:active,
  .bb:active, .cc:active,
  .gold-pill:active           { transform: scale(0.965) !important; opacity: 0.92; }

  /* A card also warms slightly, so the press reads on a big tile where a
     3% scale is easy to miss. */
  .kf-m-tile:not(.is-dark):active,
  .ml:active, .kf-m-rowcard:active { background: #F6F0E6 !important; }
  html[data-theme="dark"] .kf-m-tile:not(.is-dark):active,
  html[data-theme="dark"] .ml:active,
  html[data-theme="dark"] .kf-m-rowcard:active { background: rgba(255,255,255,0.12) !important; }

  /* Someone who has asked for less motion gets the colour change only. */
  @media (prefers-reduced-motion: reduce) {
    .kf-m-tab:active, .kf-m-fab:active, .kf-m-tile:active,
    .kf-m-quick-item:active, .kf-m-rowcard:active, .ml:active,
    button:active, .kf-btn:active { transform: none; }
  }

  /* ── The scrolling box ────────────────────────────────────────────────
     The window itself no longer scrolls; this box does. The bar and the
     circles are siblings of it, so nothing that happens inside can move
     them — no bounce, no toolbar, no momentum layer. */
  /* No page lock. The document scrolls itself, so its content can run under
     Safari's translucent bottom bar and show through it. */
  html.kf-m-locked,
  html.kf-m-locked body {
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
    overscroll-behavior: auto !important;
    /* Same colour as the page, so even a hairline anywhere it does not cover
       is invisible rather than a contrasting band. */
    background: #F5EEE3;
  }
  [data-theme="dark"] html.kf-m-locked,
  [data-theme="dark"] html.kf-m-locked body { background: #14100C; }
  .kf-m-scroll {
    /* FIXED, not absolute.
       Absolute measures against the body, and on iOS in an installed app the
       body's 100% height can resolve shorter than the screen — leaving an
       uncovered strip along the bottom showing a different colour. That is
       the band under the bar in your screenshot. Fixed measures against the
       screen itself, so it always covers it exactly. */
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 100vh;
    height: 100dvh;                      /* the visible viewport, not the tall one */
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;   /* momentum INSIDE the box is fine */
    overscroll-behavior: contain;        /* its bounce cannot reach the page */

    /* Room for the bar at the end of the box.
       The clearance used to live on the footer and the main element. Now that
       the content sits inside this box, it belongs here — otherwise the box
       scrolls to its end with the last card still underneath the bar, which
       is the cut-off text in your screenshots. 66px of bar + 22px gap + a
       little breathing room. */
    /* Enough room that the last card can be scrolled clear of the bar, but
       the content itself still runs to the bottom edge behind it. */
    padding-bottom: 96px;
  }

  /* ── Floating glass circles (theme, bell, back) ──────────────────────── */
  .kf-m-fabs {
    /* CSS-only, same reasoning as the bar — nothing measured at runtime. */
    position: fixed;
    top: 10px;
    right: 11px;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
    display: flex;
    gap: 7px;
    z-index: 900;
  }
  .kf-m-fabs.kf-m-left { right: auto; left: 11px; }
  @supports (padding: env(safe-area-inset-top)) {
    .kf-m-fabs { top: calc(10px + env(safe-area-inset-top, 0px)); }
  }

  .kf-m-fab {
    width: 44px; height: 44px;
    border: 0.5px solid rgba(255,255,255,0.95);
    border-radius: 999px;
    background: rgba(251, 246, 238, 0.76);
    -webkit-backdrop-filter: blur(28px) saturate(2);
    backdrop-filter: blur(28px) saturate(2);
    box-shadow: 0 2px 14px rgba(74,59,51,0.18);
    display: flex; align-items: center; justify-content: center;
    color: #8A7358;
    font-size: 21px;
    cursor: pointer;
    position: relative;
    padding: 0;
  }
  .kf-m-fab:active { transform: scale(0.94); }
  .kf-m-fab-dot {
    position: absolute; top: 3px; right: 4px;
    width: 8px; height: 8px; border-radius: 50%;
    background: #C25E33;
    border: 1.5px solid #FBF6EE;
  }

  /* ── The pill tab bar ────────────────────────────────────────────────
     Icons only, no labels, the way Instagram does it — and now it holds
     EVERY menu item and scrolls sideways instead of hiding the rest behind
     a "More" button. The active item gets a soft filled pill behind it.

     The white hairline edge, inner top highlight and drop shadow are what
     make it read as glass over plain white content; without them a blurred
     bar on a white page just looks white. */
  .kf-m-tabbar {
    /* Measured off the Instagram screenshot, on a 440pt-wide iPhone:
         side margin   22px  (5% of the screen width)
         bar height    60px
         gap below     22px
         icon glyph    22px
       Those are the numbers used below. The side margin is written as 5%
       so it stays in proportion on a narrower phone; the rest are absolute,
       because Instagram does not scale them either.

       No safe-area inset. Instagram's bar sits 22px from the physical bottom
       and simply lets the home indicator draw across it. Honouring the inset
       is what pushed ours a third of an inch too high. */
    position: fixed;
    left: 5%; right: 5%;
    bottom: 22px;
    height: 60px;
    box-sizing: border-box;
    display: flex; align-items: center;
    padding: 0 6px;
    border: 0.5px solid rgba(255,255,255,1);
    border-radius: 999px;
    /* SOLID, not translucent.
       Glass looked good over a photo, but over a page of text and cards the
       content sliding underneath stayed faintly visible through it — which
       reads as a smear or a stray grid rather than a deliberate effect. An
       opaque pill hides whatever passes behind it cleanly. The soft shadow
       still lifts it off the page. */
    /* Frosted glass, the finish in your recording. It is 88% opaque rather
       than the 45% I used before: enough blur and translucency to read as
       glass, but solid enough that text passing behind it does not smear
       through — which was the complaint last time. */
    /* More glass, less paint. 0.88 was nearly solid; at 0.72 with a heavier
       blur the page behind reads as a soft wash of colour through it, which
       is the finish in your recording. Still opaque enough that text passing
       behind does not smear into legible words. */
    background: rgba(251, 246, 238, 0.72);
    -webkit-backdrop-filter: blur(34px) saturate(2.1);
    backdrop-filter: blur(34px) saturate(2.1);
    border: 0.5px solid rgba(255,255,255,0.85);
    box-shadow: 0 6px 26px rgba(74,59,51,0.20), inset 0 1px 0 rgba(255,255,255,0.75);
    z-index: 950;

    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scroll-behavior: smooth;
    scroll-snap-type: x proximity;
    scrollbar-width: none;

    transform: translateZ(0) scale(1);
    -webkit-transform: translateZ(0) scale(1);
    will-change: transform, opacity;
    transform-origin: 50% 100%;          /* shrinks toward the bottom edge */
    transition: transform .22s cubic-bezier(.32,.72,0,1);
  }

  /* Scrolling down: smaller and slightly faded, so it keeps out of the way
     without disappearing. The first upward flick removes this class and the
     transition above brings it back. */
  .kf-m-tabbar.kf-m-shrunk {
    /* Scale only — NO opacity. Fading it was what let the page show through
       while scrolling, which is the smear of text across the bar. Making the
       background opaque was not enough on its own while the whole element was
       still being faded. */
    transform: translateZ(0) scale(0.86);
    -webkit-transform: translateZ(0) scale(0.86);
  }

  @media (prefers-reduced-motion: reduce) {
    .kf-m-tabbar { transition: none; }
    .kf-m-tabbar.kf-m-shrunk { transform: translateZ(0) scale(1); }
  }

  .kf-m-tabbar::-webkit-scrollbar { display: none; }

  /* Added to the home screen, iOS reserves a strip for the home indicator.
     env() covers it, but a little extra keeps the pill clearly off it. */


  .kf-m-tab {
    flex: 0 0 auto;              /* keep natural width so the row can scroll */
    display: flex; align-items: center; justify-content: center;
    text-decoration: none;
    /* Measured off your Instagram screenshot: its icons are rgb(15,19,23) —
       essentially black, not a tint. That weight is what makes the row read
       clearly at 22px. Ours are a very dark warm neutral rather than pure
       black, so the bar still belongs to the resort's palette instead of
       looking like a stock component.
       Content icons elsewhere keep the dark gold you asked for — this is the
       tab bar only. */
    color: #2E2620;
    background: none;
    border: 0;
    font: inherit;
    cursor: pointer;
    padding: 0;
    scroll-snap-align: center;
  }
  .kf-m-tab i { font-size: 26px; line-height: 1; }
  /* Labels are gone — the icon carries it, as on Instagram. Kept in the
     markup for screen readers rather than deleted. */
  .kf-m-tab > span:last-child {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  .kf-m-tab-ico {
    /* Instagram's active pill: a rounded rectangle around the icon, roughly
       66 x 44 inside a 60px bar. */
    display: flex; align-items: center; justify-content: center;
    min-width: 66px; height: 44px;
    border-radius: 999px;
    border: 0;
  }
  /* Instagram's active tab is the same black with a grey pill behind it,
     not a different colour. */
  .kf-m-tab.is-active { color: #100C08; }
  .kf-m-tab.is-active .kf-m-tab-ico {
    background: rgba(74,59,51,0.09);
    border-color: rgba(74,59,51,0.06);
  }
  .kf-m-tab:active .kf-m-tab-ico { transform: scale(0.94); }
  .kf-m-tab-dot {
    position: absolute; margin-left: 18px; margin-top: -16px;
    width: 8px; height: 8px; border-radius: 50%; background: #C25E33;
  }

  /* ── The More sheet ──────────────────────────────────────────────────── */
  .kf-m-scrim {
    position: fixed; inset: 0;
    background: rgba(40,31,24,0.28);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    z-index: 940;
    opacity: 0; pointer-events: none;
    transition: opacity .2s ease;
  }
  .kf-m-scrim.is-open { opacity: 1; pointer-events: auto; }

  .kf-m-sheet {
    position: fixed; left: 0; right: 0; bottom: 0;
    max-height: 78vh; overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 12px 13px calc(120px + env(safe-area-inset-bottom, 0px));
    border-top: 0.5px solid rgba(255,255,255,1);
    border-radius: 24px 24px 0 0;
    background: rgba(253,251,248,0.90);
    -webkit-backdrop-filter: blur(26px) saturate(1.9);
    backdrop-filter: blur(26px) saturate(1.9);
    z-index: 945;
    transform: translateY(100%);
    transition: transform .26s cubic-bezier(.32,.72,0,1);
  }
  .kf-m-sheet.is-open { transform: translateY(0); }
  .kf-m-grip {
    width: 42px; height: 5px; border-radius: 999px;
    background: rgba(74,59,51,0.16);
    margin: 0 auto 11px;
  }
  .kf-m-sheet-sec {
    font-size: 11.5px; letter-spacing: 0.13em; text-transform: uppercase;
    color: #C4B39E; margin: 18px 0 10px 3px;
  }
  .kf-m-sheet-sec:first-of-type { margin-top: 0; }
  .kf-m-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 8px; }
  .kf-m-item {
    display: flex; align-items: center; gap: 11px;
    padding: 17px 14px;
    border: 0.5px solid rgba(255,255,255,1);
    border-radius: 16px;
    background: rgba(255,255,255,0.92);
    text-decoration: none;
    color: #3a2f28;
    font-size: 14.5px;
    line-height: 1.35;
    min-height: 64px;
  }
  .kf-m-item i { font-size: 22px; color: #C1A06C; flex: none; }
  .kf-m-item:active { background: rgba(255,255,255,1); transform: scale(0.98); }
  .kf-m-item.is-danger { color: #8A5A3A; }
  .kf-m-item.is-danger i { color: #B07A5A; }


  /* ══════════════════════════════════════════════════════════════════════
     THE PAGE SKIN
     Up to here this file only replaced the NAVIGATION. The pages themselves
     still carried their original look, which is why they felt unchanged.
     Everything below restyles the page bodies to match: soft parchment
     background, glass cards, rounded rows, gold accents.
     Still mobile-only — every rule is inside the 768px block.
     ══════════════════════════════════════════════════════════════════════ */

  /* Page background: a soft wash instead of the flat slab. */
  /* ONE background for html and body, flat rather than a gradient.
     A gradient ends somewhere — below it the page fell back to a different
     colour, which is the mismatch when you scroll to the bottom. A single
     flat colour cannot do that. */
  html, body.kf-body, body {
    background: #F5EEE3 !important;
    background-image: none !important;
    color: #3a2f28 !important;
  }

  /* When the script has recoloured <body> to match the header, the page's own
     content still needs the paper colour behind it — otherwise the whole
     page would take the header's colour. These carry it instead. */
  body.kf-m-paper .page,
  body.kf-m-paper .wrap,
  body.kf-m-paper .kf-main,
  body.kf-m-paper main {
    background: #F5EEE3;
  }
  [data-theme="dark"] body.kf-m-paper .page,
  [data-theme="dark"] body.kf-m-paper .wrap,
  [data-theme="dark"] body.kf-m-paper .kf-main,
  [data-theme="dark"] body.kf-m-paper main {
    background: #14100C;
  }

  /* ── Guest inner pages: the tall hero becomes a short header strip ──── */
  .inner-hero {
    padding: 62px 14px 30px !important;
    background: linear-gradient(180deg, #F5EEE3, #E8DCC8) !important;
    border-bottom: 0 !important;
    border-radius: 0 0 26px 26px;
    margin-bottom: -16px;
  }
  .inner-hero::after { display: none !important; }
  .ih-icon  { font-size: 26px !important; margin-bottom: 6px !important; }
  .ih-eye   { font-size: 9px !important; letter-spacing: 0.18em !important; color: #9A8B78 !important; }
  .ih-title { font-size: 25px !important; color: #3a2f28 !important; margin-bottom: 4px !important; }
  .ih-hours { font-size: 11px !important; color: #8A7A68 !important; }

  /* ── Cards ────────────────────────────────────────────────────────────
     The look itself is set once, in the shared-token block near the top of
     this file, so guest and staff cannot drift apart again. An older copy of
     this rule lived here with an 18px radius and a translucent background,
     and because it came LATER in the file it quietly beat the shared one —
     which is why .ib and .kf-panel stayed different from .ml and the tiles
     however carefully the tokens were written. Only spacing is set here. */
  .ib, .wx-card, .rmap-card, .kf-panel, .kf-card {
    margin-bottom: 9px !important;
  }
  .ib-title { font-size: 17px !important; color: #3a2f28 !important; }
  .ib-body  { font-size: 13.5px !important; color: #6E5F51 !important; line-height: 1.7 !important; }
  .ib-tag {
    background: rgba(193,160,108,0.12) !important;
    border: 0.5px solid rgba(193,160,108,0.28) !important;
    color: #7A6248 !important;
    font-size: 11px !important;
    border-radius: 99px !important;
    padding: 4px 11px !important;
  }

  /* ── Menu rows ───────────────────────────────────────────────────────── */
  .ml, .lux-row, .pillar {
    background: #fff !important;
    border: 0.5px solid rgba(74,59,51,0.07) !important;
    border-radius: 16px !important;
    padding: 13px !important;
    margin-bottom: 7px !important;
    box-shadow: none !important;
  }
  .lux-row, .pillar { border-bottom: 0.5px solid rgba(74,59,51,0.07) !important; }
  .ml-ico, .lux-icon, .pillar-icon {
    width: 34px !important; height: 34px !important;
    background: rgba(193,160,108,0.10) !important;
    border: 0 !important;
    border-radius: 11px !important;
    font-size: 17px !important;
  }
  .ml-label, .lux-name, .pillar-name {
    font-size: 13.5px !important; color: #3a2f28 !important; font-weight: 400 !important;
  }
  .ml-desc, .lux-desc, .pillar-time {
    font-size: 11px !important; color: #A8977F !important; margin-top: 2px !important;
  }
  .ml-arr, .lux-arr, .pillar-arr { color: #D6C9B6 !important; font-size: 15px !important; opacity: 1 !important; }

  /* ── Section headings ────────────────────────────────────────────────── */
  .sec { padding: 14px 13px !important; }
  .sec + .sec { border-top: 0 !important; }
  .sec-eye {
    font-size: 10.5px !important; letter-spacing: 0.14em !important;
    color: #C4B39E !important; margin-bottom: 10px !important;
  }
  .sec-eye::before { display: none !important; }

  /* ── Action buttons ──────────────────────────────────────────────────── */
  .btm-bar { padding: 4px 13px 0 !important; gap: 8px !important; }
  .bb, .cc { border-radius: 15px !important; padding: 13px !important; }
  .bb i, .cc-ico { font-size: 19px !important; color: #fff !important; }
  .bb span, .cc-lbl { font-size: 11px !important; color: #fff !important; }
  .bb.dk, .cc.dk, .cc.fb { background: #8A7358 !important; }
  .contact-row { margin: 0 13px !important; gap: 8px !important; }
  .social-row { padding: 12px 13px !important; }
  .sb {
    background: #fff !important; border: 0.5px solid rgba(74,59,51,0.07) !important;
    color: #C1A06C !important; width: 42px !important; height: 42px !important;
  }

  /* ── Gold call to action ─────────────────────────────────────────────── */
  .gold-cta {
    margin: 0 13px !important;
    background: rgba(193,160,108,0.12) !important;
    border: 0.5px solid rgba(193,160,108,0.28) !important;
    border-radius: 18px !important;
    padding: 15px 14px !important;
  }
  .gold-cta-title { font-size: 18px !important; color: #3a2f28 !important; }
  .gold-pill { background: #8A7358 !important; color: #fff !important; border-radius: 99px !important; }

  /* ── Footer ──────────────────────────────────────────────────────────── */
  /* The floating bar sits over the page, so the LAST thing on every page
     needs clearance or it hides underneath. main/.kf-main already has it;
     the guest pages put their content in .wrap instead, which is why the
     WhatsApp and Feedback buttons were disappearing behind the bar. */

  .site-footer { border-top: 0 !important; }
  .wrap > :last-child { margin-bottom: 0 !important; }
  .footer-text { font-size: 10px !important; color: #C4B39E !important; }

  /* ── Staff: drop the clean-up panel from the top of the dashboard ────
     It is a destructive action and it sat above the tickets, where it is
     easy to hit by accident. Still reachable from the More sheet. */
  .kf-clean-toolbar { display: none !important; }

  /* ── DARK MODE — the whole skin, not just the bars ───────────────────── */
  /* The dark rules were keyed to [data-theme="dark"] as a DESCENDANT
     selector, so they only matched when something inside a dark element was
     styled — <html> itself never matched its own attribute that way. That is
     why html and body stayed light in dark mode while the page went dark,
     leaving a pale strip down each side where the page is narrower than the
     screen. html[data-theme] matches the element itself. */
  html[data-theme="dark"],
  html[data-theme="dark"] body.kf-body,
  html[data-theme="dark"] body,
  [data-theme="dark"] body.kf-body,
  [data-theme="dark"] body {
    background: #14100C !important;
    background-image: none !important;
    color: #EFE4D5 !important;
  }
  [data-theme="dark"] .inner-hero { background: linear-gradient(180deg,#14100C,#1E1813) !important; }
  [data-theme="dark"] .ih-title { color: #F0E6D8 !important; }
  [data-theme="dark"] .ih-hours, [data-theme="dark"] .ih-eye { color: #9A8B78 !important; }
  [data-theme="dark"] .ib,
  [data-theme="dark"] .wx-card,
  [data-theme="dark"] .rmap-card,
  [data-theme="dark"] .kf-panel,
  [data-theme="dark"] .kf-card {
    background: rgba(255,255,255,0.06) !important;
    border-color: rgba(255,255,255,0.12) !important;
    box-shadow: none !important;
  }
  [data-theme="dark"] .ib-title { color: #F0E6D8 !important; }
  [data-theme="dark"] .ib-body  { color: #B9AB99 !important; }
  [data-theme="dark"] .ml,
  [data-theme="dark"] .lux-row,
  [data-theme="dark"] .pillar {
    background: rgba(255,255,255,0.07) !important;
    border-color: rgba(255,255,255,0.12) !important;
  }
  [data-theme="dark"] .ml-label,
  [data-theme="dark"] .lux-name,
  [data-theme="dark"] .pillar-name { color: #EFE4D5 !important; }
  [data-theme="dark"] .ml-desc,
  [data-theme="dark"] .lux-desc,
  [data-theme="dark"] .pillar-time { color: #9A8B78 !important; }
  [data-theme="dark"] .ml-ico,
  [data-theme="dark"] .lux-icon,
  [data-theme="dark"] .pillar-icon { background: rgba(240,217,168,0.12) !important; }
  [data-theme="dark"] .sb {
    background: rgba(255,255,255,0.07) !important;
    border-color: rgba(255,255,255,0.12) !important;
    color: #E0C89A !important;
  }
  [data-theme="dark"] .gold-cta {
    background: rgba(240,217,168,0.10) !important;
    border-color: rgba(240,217,168,0.22) !important;
  }
  [data-theme="dark"] .gold-cta-title { color: #F0E6D8 !important; }
  [data-theme="dark"] .ib-tag {
    background: rgba(240,217,168,0.12) !important;
    border-color: rgba(240,217,168,0.24) !important;
    color: #E0C89A !important;
  }
  [data-theme="dark"] .sec-eye,
  [data-theme="dark"] .footer-text { color: #8A7C6B !important; }


  /* ══════════════════════════════════════════════════════════════════════
     LAYOUT CORRECTIONS — from your screenshots
     ══════════════════════════════════════════════════════════════════════ */

  /* 1. THE COLOUR BAND AT THE TOP.
     .page carries 56px of padding-top to clear the old fixed nav. The nav is
     hidden on mobile, so that padding was left as a strip of page background
     ABOVE the header — a different colour from the header itself, which is
     the mismatch in the screenshot. Remove it and let the header run to the
     very top of the screen. */
  .page, .page.active { padding-top: 0 !important; }

  .inner-hero {
    margin: 0 !important;
    border-radius: 0 !important;
    padding: 78px 16px 30px !important;
  }

  /* html must match, or the bounce-scroll at the top of iOS shows the old
     colour behind the page — the white fade you saw in dark mode. */

  [data-theme="dark"] .inner-hero { background: linear-gradient(180deg,#14100C,#1E1813) !important; }

  /* 2. THE HOME HERO filled the whole screen, so the page still opened the
     old way. It becomes a compact banner and the content starts straight
     after it. */
  .hero {
    min-height: 0 !important;
    height: auto !important;
    padding: 84px 16px 30px !important;
  }
  /* The "EXPLORE" scroll cue belongs to a full-screen hero. With the hero
     shortened it had nothing to point at and overlapped the weather pills. */
  .hero-scroll-cue, .hero-scroll, .scroll-cue, .explore-cue { display: none !important; }
  .hero h1, .hero-title { font-size: 30px !important; line-height: 1.18 !important; }
  .hero-sub, .hero-atoll { font-size: 11.5px !important; letter-spacing: 0.16em !important; }
  .hero-logo, .hero img { max-width: 168px !important; }

  /* 3. THE BLANK SPACE AT THE BOTTOM. The footer was 211px of mostly empty
     space, on top of the bar clearance. */
  .site-footer {
    /* Sides and top only. The BOTTOM is the bar clearance, set once for both
       portals further up — a padding shorthand here would reset it to 0,
       which is exactly what happened and left the guest footer flush against
       the bar. */
    padding-top: 0 !important;
    padding-left: 16px !important;
    padding-right: 16px !important;
    min-height: 0 !important;
  }
  .footer-rule, .footer-line, .site-footer hr { display: none !important; }
  /* Clearance for the floating bar goes on the LAST element only. It was on
     both .wrap and .site-footer, so every page carried it twice — that is
     the large empty area under the social icons in the screenshot. */
  .wrap { padding-bottom: 0 !important; }

  /* FULL WIDTH ON A PHONE.
     Eighteen guest pages carry `.wrap{max-width:430px}` in their own inline
     style — sized for a 430pt iPhone years ago. On any wider phone the page
     sits in a 430px column and the wallpaper shows down each side as two
     pale strips. That is what you circled.
     The cap is released below 769px so the page fills the screen; above that
     the desktop column rule takes over, which is what we want there. */
  .wrap, .page {
    max-width: none !important;
    width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  .site-footer, .kf-main, main { padding-bottom: 120px !important; }

  .wrap > :last-child { margin-bottom: 0 !important; }

  /* 4. READABLE SIZES — this is an app people read at arm's length, not a
     newspaper. Everything up one step. */
  body, .wrap { font-size: 16px !important; }
  .ib-title  { font-size: 20px !important; }
  .ib-body   { font-size: 15px !important; line-height: 1.65 !important; }
  .ib-tag    { font-size: 12.5px !important; padding: 6px 13px !important; }
  .ml-label, .lux-name, .pillar-name { font-size: 15.5px !important; }
  .ml-desc, .lux-desc, .pillar-time  { font-size: 12.5px !important; }
  .ml-ico, .lux-icon, .pillar-icon   { width: 40px !important; height: 40px !important; font-size: 20px !important; }
  .ml, .lux-row, .pillar             { padding: 15px !important; }
  .sec-eye   { font-size: 12px !important; }
  .ih-title  { font-size: 28px !important; }
  .ih-hours  { font-size: 13px !important; }
  .ih-eye    { font-size: 11px !important; }
  .bb span, .cc-lbl { font-size: 14px !important; }
  .bb i, .cc-ico    { font-size: 21px !important; }
  .bb, .cc          { padding: 16px !important; }
  .kf-filter-summary { font-size: 14.5px !important; }
  .kf-m-greet-hi    { font-size: 24px !important; }
  .kf-m-greet-date  { font-size: 11px !important; }

  /* The notification panel, moved out of the hidden top bar and shown as a
     sheet from the bottom. */
  #kf-bell-panel {
    display: none;
    position: fixed !important;
    left: 11px !important; right: 11px !important;
    /* Anchored to the TOP, under the bell that opened it. It used to sit at
       the bottom of the screen, which put it far from the button and made
       scrolling inside it awkward — the page behind moved instead. */
    top: 76px !important;
    bottom: auto !important;
    max-height: calc(100vh - 180px) !important;
    max-height: calc(100dvh - 180px) !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain !important;   /* its scroll stays inside it */
    width: auto !important; max-width: none !important;
    border-radius: 20px !important;
    border: 0.5px solid rgba(255,255,255,0.95) !important;
    background: rgba(253,251,248,0.96) !important;
    -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
    box-shadow: 0 8px 30px rgba(74,59,51,0.22) !important;
    z-index: 970 !important;
    transform: none !important;
  }
  /* The page's own bell CSS hides this panel with opacity:0 and
     pointer-events:none, not with display. So setting display:block showed an
     INVISIBLE, UNTAPPABLE panel — the bell appeared to open nothing, and any
     notification inside it could not be tapped. That is the bell being
     "stuck". All three have to be overridden. */
  #kf-bell-panel.kf-m-bell-open {
    display: block !important;
    opacity: 1 !important;
    visibility: visible !important;
    pointer-events: auto !important;
    transform: none !important;
  }
  #kf-bell-panel.kf-m-bell-open * { pointer-events: auto !important; }

  /* THE FOG OVER THE BELL PANEL.
     The panel sat at z-index 970 while the shell that holds the bar and the
     circles sits at 950 — close enough that a page overlay in between could
     wash over it, which is the haze you saw. Lifted well clear, and given a
     solid background rather than a translucent one so nothing shows through
     it either. */
  #kf-bell-panel {
    z-index: 2147483000 !important;
    background: #FBF6EE !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    box-shadow: 0 10px 36px rgba(74,59,51,0.28) !important;
    filter: none !important;
  }
  [data-theme="dark"] #kf-bell-panel { background: #201A14 !important; }
  /* nothing may sit on top of it */
  #kf-bell-panel.kf-m-bell-open ~ * { z-index: auto; }

  /* The close button, pinned inside the panel's own corner. */
  .kf-m-bell-x {
    position: absolute; top: 10px; right: 10px;
    width: 34px; height: 34px;
    display: flex; align-items: center; justify-content: center;
    border: 0; border-radius: 999px; cursor: pointer;
    background: rgba(74,59,51,0.08); color: #6E5539;
    font: inherit; z-index: 2;
  }
  .kf-m-bell-x i { font-size: 18px !important; }
  [data-theme="dark"] .kf-m-bell-x { background: rgba(255,255,255,0.12); color: #EFE4D5; }
  [data-theme="dark"] #kf-bell-panel {
    background: rgba(24,19,14,0.97) !important;
    border-color: rgba(255,255,255,0.14) !important;
  }


  /* ══════════════════════════════════════════════════════════════════════
     HOME SCREENS
     Guest: photo-led. Staff: action-led. Built by kf-mobile.js.
     ══════════════════════════════════════════════════════════════════════ */

  /* ── Guest ──────────────────────────────────────────────────────────── */
  .kf-m-hero { margin: 0 0 42px; }
  .kf-m-hero-photo {
    position: relative;
    /* No negative margin here any more — a negative top margin on a first
       child COLLAPSES out to its parent rather than bleeding upward, which
       is why the band kept coming back. The strip behind the status bar is
       painted from <html>, so kf-mobile.js now sets <html> to this header's
       own colour instead. That works on every page whatever its colour. */
    height: 230px;
  /* VERTICAL gradients on every header, on purpose.
     At an angle the top EDGE of a header is not one colour — measured on the
     home header it ran from rgb(128,180,196) on the left to rgb(173,204,198)
     on the right. The strip above it is a single flat colour, so it could
     only ever match one end, and the join showed as a band across the top.
     Straight top-to-bottom means the whole top edge is exactly the first
     colour stop, which is the colour the strip is painted with. */
    /* Paper-toned, not a blue sky.
       The strip above the page and the area below it are painted from ONE
       canvas colour — a page cannot have a different colour at each end. So
       while the header was blue and the page was paper, whichever colour the
       canvas took was wrong at the other end: match the top and blue appeared
       under the page when you pulled up, match the bottom and the band
       returned at the top.
       Keeping the header in the page's own family removes the conflict
       entirely rather than trading one seam for the other. */
    /* Starts on the EXACT page colour and warms downward. That way the one
       canvas colour equals the page colour AND the header's top edge, so the
       strip above and the area below the page are both a perfect match. */
    background: linear-gradient(180deg, #F5EEE3 0%, #EFE5D6 55%, #E8DCC8 100%);
    display: flex; align-items: flex-end; justify-content: center;
    padding-bottom: 44px;
  }
  /* Swap the gradient for a real island photo when you have one:
       .kf-m-hero-photo { background-image: url('/assets/home-hero.jpg');
                          background-size: cover; background-position: center; } */
  .kf-m-hero-name {
    font-family: var(--kf-font-display, Georgia, serif);
    font-size: 17px; letter-spacing: 0.22em; color: #fff;
    text-shadow: 0 1px 10px rgba(0,0,0,0.28);
  }
  .kf-m-hero-sub {
    font-size: 8.5px; letter-spacing: 0.34em; margin-top: 4px;
    color: rgba(255,255,255,0.88);
  }
  .kf-m-stats {
    position: relative; margin: -34px 13px 0;
    display: flex; align-items: center; justify-content: space-around;
    padding: 13px 8px;
    background: rgba(255,255,255,0.88);
    -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
    border: 0.5px solid rgba(255,255,255,1);
    border-radius: 19px;
    box-shadow: 0 4px 18px rgba(74,59,51,0.10);
  }
  .kf-m-stats > div { text-align: center; }
  .kf-m-stats b { display: block; font-size: 18px; color: #3a2f28; font-weight: 500; }
  .kf-m-stats span {
    display: block; font-size: 9px; letter-spacing: 0.1em;
    text-transform: uppercase; color: #B3A08B; margin-top: 3px;
  }
  .kf-m-stats i { width: 0.5px; align-self: stretch; background: rgba(74,59,51,0.12); }

  .kf-m-hi {
    font-family: var(--kf-font-display, Georgia, serif);
    font-size: 25px; color: #3a2f28;
    margin: 20px 14px 13px;
  }

  .kf-m-quick {
    display: grid; grid-template-columns: repeat(4, minmax(0,1fr));
    gap: 9px; margin: 0 13px 6px;
  }
  .kf-m-quick-item { text-decoration: none; text-align: center; display: block; }
  .kf-m-quick-ico {
    display: flex; align-items: center; justify-content: center;
    height: 58px; border-radius: 18px;
    background: #fff; border: 0.5px solid rgba(74,59,51,0.07);
  }
  .kf-m-quick-ico i { font-size: 24px; color: #C1A06C; }
  .kf-m-quick-item > span:last-child {
    display: block; font-size: 11.5px; color: #7A6A5A; margin-top: 6px;
  }
  .kf-m-quick-item:active .kf-m-quick-ico { transform: scale(0.96); }

  [data-theme="dark"] .kf-m-hero-photo {
    background: linear-gradient(180deg, #14100C 0%, #191410 55%, #1E1813 100%);
  }

  /* ── Staff ──────────────────────────────────────────────────────────── */
  .kf-m-sboard {
    padding: calc(10px + env(safe-area-inset-top, 0px)) 2px 6px;
  }
  .kf-m-sday {
    font-size: 10.5px; letter-spacing: 0.16em;
    text-transform: uppercase; color: #BFAE99;
  }
  .kf-m-sboard .kf-m-hi { margin: 4px 0 14px; }
  .kf-m-tiles { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 9px; }
  .kf-m-tile {
    display: block; text-decoration: none;
    background: #fff; border: 0.5px solid rgba(74,59,51,0.07);
    border-radius: 18px; padding: 15px;
    min-height: 104px;
  }
  .kf-m-tile i { font-size: 23px; color: #C1A06C; }
  .kf-m-tile b {
    display: block; font-size: 14px; color: #3a2f28;
    font-weight: 500; margin-top: 9px;
  }
  .kf-m-tile span { display: block; font-size: 10.5px; color: #BFAE99; margin-top: 2px; }
  .kf-m-tile.is-dark {
    background: #8A7358 !important;
    border-color: #8A7358 !important;
  }
  .kf-m-tile.is-dark i { color: #fff; }
  .kf-m-tile.is-dark b { color: #fff; }
  .kf-m-tile.is-dark span { color: rgba(255,255,255,0.78); }
  .kf-m-tile:active { transform: scale(0.98); }

  /* ── Dark ───────────────────────────────────────────────────────────── */
  [data-theme="dark"] .kf-m-stats {
    background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.14);
  }
  [data-theme="dark"] .kf-m-stats b { color: #F0E6D8; }
  [data-theme="dark"] .kf-m-hi { color: #F0E6D8; }
  [data-theme="dark"] .kf-m-quick-ico,
  [data-theme="dark"] .kf-m-tile {
    background: rgba(255,255,255,0.07); border-color: rgba(255,255,255,0.12);
  }
  [data-theme="dark"] .kf-m-tile b { color: #EFE4D5; }
  [data-theme="dark"] .kf-m-tile.is-dark { background: #6E5539; border-color: #6E5539; }
  [data-theme="dark"] .kf-m-quick-item > span:last-child { color: #A99B8C; }


  /* ══════════════════════════════════════════════════════════════════════
     READABILITY FLOOR
     Audited every visible text node on the real pages: the weather card,
     the tide table, the map card and the footer were still running at
     10–13px, well under comfortable reading size. Nothing carrying real
     information is below 14px now, and small icons are up with it.
     This is an in-villa app used by guests of every age, often in low
     evening light — legibility beats density.
     ══════════════════════════════════════════════════════════════════════ */

  /* Weather card */
  .wx-card, .wx-card * { font-size: 15px; }
  .wx-loc        { font-size: 15px !important; }
  .wx-cond       { font-size: 15px !important; }
  .wx-feels      { font-size: 15px !important; }
  .wx-temp, .wx-big { font-size: 46px !important; }
  .wx-stat-lbl   { font-size: 13.5px !important; letter-spacing: 0.08em !important; }
  .wx-stat-val   { font-size: 17px !important; }
  .wx-sec-label  { font-size: 14px !important; letter-spacing: 0.12em !important; }
  .wx-tc-type, .wx-tc-ht, .wx-tc-time { font-size: 14px !important; }
  .wx-tide-badge { font-size: 14px !important; padding: 5px 12px !important; }

  /* Map card */
  .rmap-sub, .rmap-pill, .map-coord { font-size: 14px !important; }
  .rmap-title { font-size: 19px !important; }

  /* Footer and small print */
  /* The closing line and its decorative rule are removed on mobile — they
     were a whole screenful of nothing at the end of every page. */
  .footer-text, .footer-rule, .footer-line { display: none !important; }

  /* Page furniture */
  .ih-eye   { font-size: 13px !important; letter-spacing: 0.16em !important; }
  .ih-hours { font-size: 15px !important; }
  .sec-eye  { font-size: 13.5px !important; }
  .ib-tag   { font-size: 14px !important; padding: 7px 14px !important; }
  .ml-desc, .lux-desc, .pillar-time { font-size: 14px !important; }
  .ml-label, .lux-name, .pillar-name { font-size: 17px !important; }
  .ib-body  { font-size: 16px !important; line-height: 1.7 !important; }
  .ib-title { font-size: 21px !important; }

  /* Home screens */
  .kf-m-hero-sub  { font-size: 11px !important; }
  .kf-m-stats b   { font-size: 20px !important; }
  .kf-m-stats span{ font-size: 12px !important; }
  .kf-m-quick-item > span:last-child { font-size: 13px !important; }
  .kf-m-quick-ico i { font-size: 27px !important; }
  .kf-m-quick-ico   { height: 64px !important; }
  .kf-m-tile b    { font-size: 15.5px !important; }
  .kf-m-tile span { font-size: 12.5px !important; }
  .kf-m-tile i    { font-size: 26px !important; }
  .kf-m-sday      { font-size: 12px !important; }

  /* Icons that were still small */
  .ml-ico i, .lux-icon i, .pillar-icon i { font-size: 22px !important; }
  .sb i { font-size: 21px !important; }
  .sb   { width: 48px !important; height: 48px !important; }
  .wx-card i, .rmap-card i { font-size: 20px !important; }

  /* Tab bar: icons a touch larger again, and a taller tap target. */
  /* theme.css carries `i.ti { font-size: 1.3rem !important }` — 23.92px.
     My rule was `.kf-m-tab i`, the SAME specificity, so the later of the two
     won and staff icons came out smaller than guest ones. The guest pages do
     not load that rule, which is why only staff was affected and why the two
     bars looked like different icon sets. Scoping to the bar raises the
     specificity so one size applies everywhere. */
  /* 22px glyphs — measured off the screenshot, every Instagram icon is 22px. */
  /* 22px — the exact glyph size measured in the Instagram screenshot. */
  .kf-m-tabbar .kf-m-tab i.ti,
  .kf-m-tabbar .kf-m-tab i {
    font-size: 22px !important;
    vertical-align: 0 !important;
    color: inherit !important;      /* beats the global gold rule */
  }
  .kf-m-fab i.ti, .kf-m-fab i { font-size: 22px !important; vertical-align: 0 !important; }
  .kf-m-tile i.ti { font-size: 26px !important; vertical-align: 0 !important; }
  .kf-m-quick-ico i.ti { font-size: 27px !important; vertical-align: 0 !important; }

  /* The stats card is tappable — it jumps to the weather section. */
  .kf-m-stats { cursor: pointer; }
  .kf-m-stats:active { transform: scale(0.99); }
  .kf-m-tab-ico { min-width: 66px !important; height: 50px !important; }
  .kf-m-fab { width: 46px !important; height: 46px !important; font-size: 22px !important; }

  /* Anything still tiny that was not named above. Kept last so the explicit
     rules win, and scoped to text the guest actually reads. */
  .wrap p, .wrap li, .wrap td, .wrap th, .kf-main p, .kf-main li { font-size: 16px; }

  /* A button must never be the smallest text on the screen. */
  .gold-pill { font-size: 15px !important; padding: 11px 20px !important; }
  .gold-cta-eye, .map-cta { font-size: 14px !important; }

  /* Any remaining icon inside page content, lifted to a readable size.
     No !important, so the explicit sizes above (tab bar 28px, row tiles
     22px) still win over it. */
  .wrap i.ti, .kf-main i.ti { font-size: 20px; }

  /* ── The greeting on home screens ─────────────────────────────────────── */
  .kf-m-greet { padding: 6px 2px 12px; }
  .kf-m-greet-date {
    font-size: 8.5px; letter-spacing: 0.16em; text-transform: uppercase;
    color: #BFAE99;
  }
  .kf-m-greet-hi {
    font-family: var(--kf-font-display, Georgia, serif);
    font-size: 21px; color: var(--kf-ink, #3a2f28);
    margin-top: 3px;
  }

  /* Page titles are redundant once the tab bar names the place.
     The staff dashboard's title is a bare <h1 style="font-size:1.5rem">, not
     a class, so a class-only rule missed it — hence "Live Dashboard" still
     showing under the greeting. The h1 inside the main area is hidden too. */
  .kf-page-title, .kf-eyebrow { display: none !important; }
  .kf-main > h1:first-of-type,
  main > h1:first-of-type,
  .kf-main > .kf-dash-header h1,
  main > .kf-dash-header h1 { display: none !important; }

  /* ── Dark mode ────────────────────────────────────────────────────────── */
  [data-theme="dark"] .kf-m-fab {
    background: #201A14;
    border-color: rgba(255,255,255,0.18);
    color: #E0D3C2;
    box-shadow: none;
  }
  [data-theme="dark"] .kf-m-fab-dot { border-color: #17120E; background: #E8703F; }
  [data-theme="dark"] .kf-m-tabbar {
    background: rgba(32, 26, 20, 0.74);
    -webkit-backdrop-filter: blur(34px) saturate(2.1);
    backdrop-filter: blur(34px) saturate(2.1);
    border-color: rgba(255,255,255,0.14);
    box-shadow: 0 6px 26px rgba(0,0,0,0.55);
  }
  [data-theme="dark"] .kf-m-tab { color: #9A8B78; }
  [data-theme="dark"] .kf-m-tab.is-active { color: #F0D9A8; }
  [data-theme="dark"] .kf-m-tab.is-active .kf-m-tab-ico {
    background: rgba(240,217,168,0.16); border-color: rgba(240,217,168,0.34);
  }
  [data-theme="dark"] .kf-m-sheet {
    background: rgba(20,16,12,0.92);
    border-top-color: rgba(255,255,255,0.14);
  }
  [data-theme="dark"] .kf-m-item {
    background: rgba(255,255,255,0.07);
    border-color: rgba(255,255,255,0.12);
    color: #EFE4D5;
  }
  [data-theme="dark"] .kf-m-grip { background: rgba(255,255,255,0.2); }
  [data-theme="dark"] .kf-m-greet-hi { color: #F0E6D8; }

  /* ── Older browsers ───────────────────────────────────────────────────
     backdrop-filter is what makes the glass. Without it a translucent bar
     over a busy page is unreadable, so those browsers get a solid bar
     instead — plainer, but perfectly usable. Given the Android trouble this
     site has had, that fallback is not optional. */
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .kf-m-tabbar { background: #FBF6EE; }
    .kf-m-fab    { background: #FBF6EE; }
    .kf-m-sheet  { background: #FDFBF8; }
    [data-theme="dark"] .kf-m-tabbar,
    [data-theme="dark"] .kf-m-fab { background: #1C1611; }
    [data-theme="dark"] .kf-m-sheet { background: #14100C; }
  }

  @media (prefers-reduced-motion: reduce) {
    .kf-m-sheet, .kf-m-scrim { transition: none; }
  }
}

/* ══════════════════════════════════════════════════════════════════════
   DESKTOP — the same design, wider. Only genuine differences live here.
   ══════════════════════════════════════════════════════════════════════ */
@media (min-width: 769px) {
  /* The pill sits centred rather than edge to edge, and shows text labels
     because there is room and a bare icon row is harder to read on a big
     screen. */
  .kf-m-tabbar,
  .kf-m-shell > .kf-m-tabbar {
    left: 50% !important;
    right: auto !important;
    transform: translateX(-50%) translateZ(0);
    width: auto;
    /* A pill, not a ribbon. With labels on, thirteen tabs would stretch
       almost the full width of a large screen and stop reading as one
       control. Capped, and it still scrolls sideways like it does on a
       phone. */
    /* The bar grows a little on a wide screen too, so it does not look
       stranded under a much wider page. */
    max-width: min(920px, calc(100vw - 48px));
    padding: 0 8px;
    gap: 2px;
  }
  .kf-m-tabbar.kf-m-shrunk {
    transform: translateX(-50%) translateZ(0) scale(0.92);
  }
  .kf-m-tab { flex-direction: row; }
  .kf-m-tab-ico { min-width: 0; padding: 0 4px 0 12px; height: 44px; }
  /* the label is hidden on phones; bring it back here */
  .kf-m-tab > span:last-child {
    position: static; width: auto; height: auto; clip: auto;
    font-size: 13px; padding-right: 14px; white-space: nowrap;
  }
  .kf-m-tabbar .kf-m-tab i.ti { font-size: 19px !important; }
  .kf-m-tab.is-active .kf-m-tab-ico { background: none; }
  .kf-m-tab.is-active { background: rgba(74,59,51,0.09); border-radius: 999px; }

  /* A READING COLUMN.
     Without this the cards stretch the full width of the monitor — a weather
     panel a metre wide, rows of text far too long to scan. Everything sits in
     a centred column of a comfortable width, which is also what makes the
     desktop and the phone look like the same product rather than the same
     content stretched. */
  /* AUTO-FIT, any monitor.
     A fixed 1080px looked right on one screen and wrong on the next. The
     column now grows with the window up to a comfortable maximum and always
     keeps a margin at the sides, so an 18in, a 24in and a 32in all look
     deliberate rather than stretched or stranded. */
  /* !important, because the staff pages set their own full-bleed width with
     more specific rules — that is why they filled the whole monitor while the
     guest pages sat in a column. */
  /* Above 769px the page returns to a centred column. The rule that frees it
     to full width is for phones only. */
  /* 1280px left 200px of empty wallpaper down each side of a 1680 monitor —
     a column floating in the middle of the screen rather than a page using
     it. Widened to 96% of the window, capped at 1800 so a very wide monitor
     does not stretch a line of text past comfortable reading length. */
  .wrap, .page, .kf-main, main,
  .kf-shell, .kf-container, .kf-content, .kf-page, form.kf-form {
    width: min(96vw, 1800px) !important;
    max-width: none !important;
    margin-left: auto !important;
    margin-right: auto !important;
    box-sizing: border-box;
  }

  /* Staff pages put their tables in a full-bleed wrapper that deliberately
     escapes the column with negative margins. On a phone that was right; on a
     monitor it threw the table past the edge of the screen, which is the
     content running off the side in your screenshots. */
  /* Desktop shows the real table and never the cards — a table is the right
     shape when there is room for it. */
  .kf-m-cards { display: none !important; }
  .kf-m-tablehidden { display: block !important; }

  .kf-table-wrap {
    width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    overflow-x: auto;
    border-radius: 16px;
  }
  table { width: 100%; }

  /* CLEAR OF THE STATUS BAR.
     iOS blurs whatever sits directly behind the status bar, so a heading that
     starts at the very top of the page comes out hazy and half-unreadable —
     that is the fog over "Good evening". 22px was not enough to escape it.
     The safe-area inset is the height iOS itself reserves there, so adding it
     puts the content below the blurred strip instead of inside it. */
  /* The staff pages set their own smaller top padding with a more specific
     rule, so this was losing and the first heading sat at y=20 — inside the
     strip iOS blurs behind the status bar. That is the haze over "Tell us
     what went wrong". Scoped to body so it wins. */
  body .kf-main,
  body main,
  body .wrap,
  body .page,
  body form.kf-form {
    padding-top: calc(22px + env(safe-area-inset-top, 0px)) !important;
  }
  /* Pages whose header runs to the very top keep their own spacing — the
     header is meant to sit behind the status bar; the text inside it is
     already positioned clear. */
  .kf-m-hero ~ *, .inner-hero ~ * { padding-top: 0 !important; }
  .kf-m-hero, .inner-hero { max-width: none !important; }   /* banners stay full width */
  /* The side margins have to be cleared as well as the width set. These
     blocks carry `margin: 0 13px` from the phone layout, and 13px on top of a
     full-width block is what pushed the page 14px past the right edge. */
  /* These sit INSIDE .kf-main or .wrap, which is already the reading column.
     Giving them the column's own width again made them wider than the
     container's content box — the dashboard tiles ran 30px past the right
     edge of the page while the table beneath stopped 60px short of them, so
     nothing lined up. They simply fill their parent now. */
  .kf-m-stats, .kf-m-hi, .kf-m-quick, .kf-m-sboard,
  .sec, .site-footer, .btm-bar, .contact-row, .social-row, .gold-cta,
  .kf-m-tiles, .kf-table-wrap, .kf-m-cards {
    width: 100% !important;
    max-width: 100% !important;
    margin-left: 0 !important; margin-right: 0 !important;
    box-sizing: border-box;
  }
  /* The dashboard board carries 2px of side padding from the phone layout.
     Two pixels is invisible on its own but it is enough to leave the tiles
     and the table below them out of line with each other, which is what
     reads as "not quite right" on a big screen. */
  .kf-m-sboard { padding-left: 0 !important; padding-right: 0 !important; }

  /* THE TYPE COLUMN COMES BACK.
     theme.css hides it below about 1500px, from when the page was capped at
     1280 and there was genuinely no room. The column is now 96% of the
     window, so on a 1440 laptop — the commonest size in an office — there is
     space for it, and "Request" or "Complaint" is the first thing anyone
     wants to know about a ticket. Hiding it there lost real information.

     Priority stays hidden on purpose: it is already shown as the STANDARD /
     URGENT / CRITICAL chip inside the Status column, so the separate column
     would say the same thing twice. */
  th.kf-col-type, td.kf-col-type { display: table-cell !important; }
  /* Cards per row scale with the width instead of being fixed at three. */
  .sec-grid, .kf-m-cols, .kf-m-tiles {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)) !important;
  }

  /* Cards in columns instead of a single stack. */
  /* Same width as everything else in the column. It had its own 720px cap,
     which left it floating out of line with the cards above and below it. */
  .kf-m-quick { grid-template-columns: repeat(4, minmax(0,1fr)); max-width: 1080px; }
  .kf-m-quick-item > span:last-child { display: block; }
  .kf-m-tiles { grid-template-columns: repeat(4, minmax(0,1fr)); }
  .sec, .wrap > .sec { max-width: 1100px; margin-left: auto; margin-right: auto; }
  /* Menu and outlet rows read badly at 1000px wide, so they sit two across. */
  .sec .ml, .sec .lux-row, .sec .pillar { width: 100%; }
  .sec { display: block; }
  .kf-m-two {
    display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px;
  }
  .sec-grid, .kf-m-cols {
    display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 12px;
  }

  /* The header banner can be a little taller with the extra room. */
  .inner-hero { padding: 96px 24px 40px !important; }
  .kf-m-hero-photo { height: 300px; }

  /* The floating circles move in from the edge. */
  .kf-m-fabs { top: 16px; right: 20px; }
}

/* The <html> background in dark mode.
   It was only set inside the mobile media block, but the browser paints the
   area behind the status bar and the over-scroll from <html> — so in dark
   mode that strip stayed light. This sits outside the block on purpose, and
   only ever applies when dark mode is actually on. */
/* !important, because the light rule above is also !important — without it
   the dark rule loses and the strip behind the status bar stays pale. */
html[data-theme="dark"] { background: #14100C !important; }
html[data-theme="dark"] body { background: #14100C !important; }


/* ══════════════════════════════════════════════════════════════════════
   CONTRAST FLOOR — deliberately the LAST thing in this file.
   It first lived in the middle, and a rule further down (.ml-desc at
   the old line 919) quietly overrode it, so half of it never applied.
   At the end nothing can come after it.
   ══════════════════════════════════════════════════════════════════════ */

/* THE ROOT CAUSE for most of the pale text on the staff side.
   theme.css defines   --kf-ink-faint: rgba(28,20,16,0.4)
   — ink at 40% opacity. Every label, count, empty state and tier label
   built on that variable inherited it: 138 elements on Manage
   Departments alone, all at roughly 2.5 : 1. Setting the variable to a
   solid colour fixes every one of them at once, instead of chasing them
   element by element. */
/* Specificity matters here. theme.css sets this on
   :root:not([data-theme="dark"])  — specificity (0,2,0) — inside a
   prefers-color-scheme media query. A plain :root override (0,1,0) LOST
   to it, so the 40% ink survived on every page where the phone itself was
   set to light mode. html:root:not(...) is (0,2,1) and wins. */
html:root:not([data-theme="dark"]),
html[data-theme="light"],
html:root {
  --kf-ink-faint: #6B5A48;
  --kf-ink-soft:  #5A4A3A;
}
html:root[data-theme="dark"] {
  --kf-ink-faint: #C9B9A2;
  --kf-ink-soft:  #DCCDB8;
}

  /* ── A CONTRAST FLOOR ──────────────────────────────────────────────────
     Measured on every page in both themes. The secondary text colours were
     decorative taupes that looked soft but sat below the readable minimum:
         .ml-desc   2.46 : 1        .tag      2.25 : 1
         .ih-eye    2.87 : 1        (need 4.5 : 1 for text this size)
     and the WhatsApp buttons put white text on #25D366 at 1.98 : 1.
     These all read as "pale" rather than "broken", which is why they
     survived — but on a phone outdoors in Maldivian sunlight they are
     genuinely hard to read. */

  /* Secondary text: 2.25-2.87 -> 5.73 : 1 */
  .ml-desc, .lux-desc, .tag, .ih-eye, .qty-group-label, .sec-eye, .section-desc,
  .field-hint, .kf-lede, .kf-sub, .kf-file-meta, .kf-eyebrow, .ib-tag,
  .vol, .ih-sub, .kf-dash-date, .drawer-section-label, .kf-tier-mobile-label,
  .kf-bell-panel-count, .kf-bell-empty, .kf-m-sday, .kf-dept-tab,
  small, em {
    color: #6B5A48 !important;
  }
  html[data-theme="dark"] .ml-desc, html[data-theme="dark"] .tag,
  html[data-theme="dark"] .ih-eye, html[data-theme="dark"] .qty-group-label,
  html[data-theme="dark"] .sec-eye, html[data-theme="dark"] .section-desc,
  html[data-theme="dark"] .field-hint, html[data-theme="dark"] .kf-lede,
  html[data-theme="dark"] .kf-sub, html[data-theme="dark"] .kf-file-meta,
  html[data-theme="dark"] .kf-eyebrow, html[data-theme="dark"] .ib-tag,
  html[data-theme="dark"] .vol, html[data-theme="dark"] .ih-sub,
  html[data-theme="dark"] .kf-dash-date, html[data-theme="dark"] .lux-desc,
  html[data-theme="dark"] .drawer-section-label, html[data-theme="dark"] .kf-tier-mobile-label,
  html[data-theme="dark"] .kf-bell-panel-count, html[data-theme="dark"] .kf-bell-empty,
  html[data-theme="dark"] .kf-m-sday, html[data-theme="dark"] .kf-dept-tab,
  html[data-theme="dark"] .gold-cta-eye, html[data-theme="dark"] .wx-tc-type,
  html[data-theme="dark"] small, html[data-theme="dark"] em {
    color: #C9B9A2 !important;
  }

  /* WhatsApp buttons: WhatsApp's own darker brand green. 1.98 -> 5.42 : 1 */
  .bb.wa, .cc.wa, a[href*="wa.me"].bb, a[href*="wa.me"].cc,
  .btn-wa, .wa-btn, a.bb[href*="whatsapp"], a.cc[href*="whatsapp"] {
    background: #0F7A3F !important;
    color: #FFFFFF !important;
  }
  a[href*="wa.me"].bb i, a[href*="wa.me"].cc i,
  a.bb[href*="whatsapp"] i, a.cc[href*="whatsapp"] i { color: #FFFFFF !important; }

  /* Feedback and other brown buttons: 3.38 -> 6.45 : 1 */
  .bb.fb, .cc.fb, .bb.feedback, .cc.feedback, .gold-pill {
    background: #6E5B4A !important;
    color: #FFFFFF !important;
  }

/* Booking slot pills in dark mode: rgb(110,85,71) on the dark card was
   1.83 : 1 — the "Available" / "Booked" labels were nearly invisible. */
html[data-theme="dark"] .pill {
  color: #EFE4D5 !important;
  border-color: rgba(255,255,255,0.22) !important;
}

/* Staff dashboard tile subtitles ("New complaint or request") were
   2.16 : 1, and the department tabs on Manage Menus 2.07 : 1. */
.kf-m-tile:not(.is-dark) span, .kf-m-tile:not(.is-dark) small {
  color: #6B5A48 !important;
}
html[data-theme="dark"] .kf-m-tile:not(.is-dark) span,
html[data-theme="dark"] .kf-m-tile:not(.is-dark) small { color: #C9B9A2 !important; }
a.kf-dept-tab, .kf-dept-tab a, .kf-dept-tabs a { color: #5A4A3A !important; }
html[data-theme="dark"] a.kf-dept-tab,
html[data-theme="dark"] .kf-dept-tab a,
html[data-theme="dark"] .kf-dept-tabs a { color: #DCCDB8 !important; }

/* The ACTIVE department tab was the palest one on the page — 2.07 : 1 —
   when it should be the one that stands out. Its own .active rule was more
   specific than the general tab rule, so it kept the washed-out colour.
   Now it is the darkest and heaviest, which is what "you are here" means. */
a.kf-dept-tab.active, .kf-dept-tab.active {
  color: #3A2F28 !important;
  font-weight: 600 !important;
}
html[data-theme="dark"] a.kf-dept-tab.active,
html[data-theme="dark"] .kf-dept-tab.active {
  color: #F2EADF !important;
}

/* RATING COLUMN HEADINGS (feedback form) — "EXCELLENTGOOD".
   My earlier table-header fix gave every <th> letter-spacing and a larger
   size. That suits a wide staff table, but the feedback form has four narrow
   rating columns, and "EXCELLENT" then needed 71px in a 59px column — it
   ran straight into "GOOD".
   Targeted by the table's own class, .rating-table — NOT by :has(). :has()
   needs Chrome 105 / Safari 15.4, and the Huawei browser tested on this
   site reports Chrome 99, where the whole rule would be silently ignored
   and the overflow would come straight back.
   The size scales with the screen so it still fits on an iPhone SE. */
.rating-table th {
  letter-spacing: 0 !important;
  font-size: clamp(8.5px, 2.3vw, 11px) !important;
  text-align: center !important;
  padding-left: 1px !important;
  padding-right: 1px !important;
  /* WRAP, don't squeeze. English fits on one line, but the form also comes
     in German and Italian, and "Durchschnittlich" needs 84px in a 50px
     column — no font size fixes that. So the heading breaks onto two lines,
     hyphenated properly: the page sets <html lang> when the language
     changes, which is what tells the browser which dictionary to use.
     overflow-wrap is the fallback for a browser with no dictionary for that
     language: an unhyphenated break is better than text running into the
     next column. */
  white-space: normal !important;
  -webkit-hyphens: auto;
  hyphens: auto;
  overflow-wrap: anywhere;
  word-break: normal;
  line-height: 1.15 !important;
  vertical-align: bottom;
}

/* ── ICONS ON FILLED BUTTONS ─────────────────────────────────────────────
   Every icon on the site is painted one gold, so staff and guest pages match.
   That rule never looked at what the icon sits ON. On a filled button it put
   a gold icon on a brown button:
       Share Your Feedback star     1.08 : 1   (12 pages — the one circled)
       Facebook button, Dive         1.33 : 1
       report "new" button           1.33 : 1
       staff Menus tile, dark mode   2.76 : 1
   The star was effectively invisible, which reads as a missing icon.

   An icon inside a filled button now takes the BUTTON'S OWN TEXT COLOUR.
   That colour was already chosen to stand out against the button, so the
   icon matches its label — the white star under a white "Share Your
   Feedback". It is a principle, not a list of fixes: any filled button added
   later gets a visible icon automatically.
   Specificity (0,2,3)+ beats the gold rule's (0,1,2); last in the file beats
   anything earlier. */
html body a.bb i.ti, html body button.bb i.ti, html body .bb [class*="ti-"],
html body a.cc i.ti, html body button.cc i.ti, html body .cc [class*="ti-"],
html body .kf-btn i.ti, html body .kf-btn [class*="ti-"],
html body .gold-pill i.ti, html body .gold-pill [class*="ti-"],
html body .kf-m-tile.is-dark i.ti, html body .kf-m-tile.is-dark [class*="ti-"],
html body button[type="submit"] i.ti {
  color: inherit !important;
  opacity: 1 !important;
}

/* Empty-state icons (e.g. "no tickets yet" on the report) were faded to
   1.68 : 1. Still quiet, but now clearly visible. */
html body .kf-rep-empty i.ti, html body .kf-rep-empty [class*="ti-"],
html body [class*="empty"] > i.ti {
  color: #8A7358 !important;
  opacity: 1 !important;
}
html[data-theme="dark"] body .kf-rep-empty i.ti,
html[data-theme="dark"] body .kf-rep-empty [class*="ti-"],
html[data-theme="dark"] body [class*="empty"] > i.ti {
  color: #B9A68A !important;
}

/* ── THE "DARK" BUTTON AND TILE VARIANTS ─────────────────────────────────
   .bb.dk (e.g. the Facebook button on Dive) and the staff dashboard's dark
   .kf-m-tile.is-dark (the "Menus" tile) had a medium-brown background with
   DARK or brown text:
       Dive Facebook button   label and icon 2.89 : 1
       staff Menus tile       tile text rgb(125,99,85) on rgb(138,115,88)
   Now icons correctly follow their button's text colour, the text itself had
   to be fixed. White on the same deeper brown the feedback button uses
   (#6E5B4A, 6.45 : 1), so every brown button on the site matches. */
html body .bb.dk, html body a.bb.dk, html body .kf-m-tile.is-dark {
  background: #6E5B4A !important;
  color: #FFFFFF !important;
}
html body .bb.dk *, html body .kf-m-tile.is-dark *,
html body .bb.dk i.ti, html body .kf-m-tile.is-dark i.ti {
  color: #FFFFFF !important;
}
/* the small line under the tile title stays secondary, but readable */
html body .kf-m-tile.is-dark span, html body .kf-m-tile.is-dark small {
  color: rgba(255,255,255,0.86) !important;
}

/* ── THE FEEDBACK FORM INSIDE THE POP-UP ─────────────────────────────────
   No toolbar and no theme button in a small window inside another page: the
   guest already has both behind it, and a second theme button meant the form
   and the site could disagree. The form simply matches the site now. */
html.kf-embed .kf-m-tabbar,
html.kf-embed .kf-m-shell,
html.kf-embed .kf-m-fabs,
html.kf-embed .kf-m-fab { display: none !important; }
/* the toolbar is gone, so the space kept clear for it goes too */
html.kf-embed .kf-m-scroll,
html.kf-embed body, html.kf-embed .wrap, html.kf-embed main, html.kf-embed .kf-main {
  padding-bottom: 0 !important;
}

/* ── TICK BOXES AND RADIO BUTTONS ARE NOT TEXT FIELDS ────────────────────
   The site makes every input full width and display:block. For a text field
   that is right; for a tick box it is not. A checkbox came out 105px wide and
   on its own line, which squeezed its label into a narrow column — "Require
   guests to sign in" stacked onto three lines, and "remove the saved key"
   onto three more. Same cause as the number box on Menu Order.
   Locked here for the whole site, so any page with a tick list reads
   normally. */
html body input[type="checkbox"],
html body input[type="radio"] {
  width: auto !important;
  min-width: 0 !important;
  max-width: none !important;
  display: inline-block !important;
  flex: 0 0 auto !important;
  margin: 0 !important;
  vertical-align: middle;
}
