/* ============================================================================
   Partyhelp venue portal - mobile app shell
   ----------------------------------------------------------------------------
   Loaded on every venue-panel screen, so a page nobody has specifically styled
   still gets app-like touch targets, spacing and a bottom tab bar.

   Everything is inside a max-width query: desktop is untouched.
   Brand: ph-purple-600 #7c3aed (primary), 700 #6d28d9, 400 #a78bfa.
   ========================================================================== */

:root {
    --ph-purple-400: #a78bfa;
    --ph-purple-500: #8b5cf6;
    --ph-purple-600: #7c3aed;
    --ph-purple-700: #6d28d9;
    --ph-tabbar-h: 4.25rem;
    --ph-safe-b: env(safe-area-inset-bottom, 0px);
    --ph-safe-t: env(safe-area-inset-top, 0px);
}

/* Both of these are injected into every venue page by a render hook, at every
   width, so each must default to hidden out here. The phone query below turns
   them on. Without this the brand's 3507x1304 logo has no sizing rule on a
   desktop and renders at container width, burying the page under it. */
/* Filament's modal container is z-40 and sits EARLIER in the document than the
   strip, which a BODY_END hook appends to <body>. At equal z-index the later
   element wins, so the strip would paint over the modal - and because the
   footer actions are column-reverse, the bottom-most control is the confirm
   button. A venue tapping "Purchase" would have hit "Credits" instead. Sit
   below the modal layer, and get out of the way entirely while one is open. */
.ph-tabbar { display: none; }
.ph-topbar-brand { display: none; }

@media (max-width: 767px) {

/* --- 1. Shell -------------------------------------------------------------
   Hide the sidebar and its hamburger outright. On a phone the bottom tab bar
   is the navigation; a drawer behind a hamburger is a second, competing one. */

.fi-sidebar,
.fi-sidebar-close-overlay,
.fi-topbar-open-sidebar-btn,
.fi-topbar-close-sidebar-btn,
.fi-layout-sidebar-toggle-btn-ctn { display: none !important; }

.fi-main-ctn { padding-left: 0 !important; margin-left: 0 !important; }

/* The page heading sat flush to the screen edge while every card below it was
   inset, and carried a 2rem gap underneath. */
.fi-header { padding-block: 0.25rem 0 !important; row-gap: 0.5rem !important; }
.fi-header-heading { padding-inline: 0.25rem; }

/* The header block carried a 2rem gap to the content below it, which on a phone
   reads as the page having lost something. */
.fi-page-header-main-ctn {
    padding-top: 0.75rem !important;
    padding-bottom: 0.875rem !important;
    row-gap: 0.875rem !important;
}

/* Compact sticky header: brand on the left, user menu on the right. */
/* The real markup is <div class="fi-topbar-ctn"><nav class="fi-topbar">, so
   ".fi-topbar > nav" matches nothing. The ctn is the sticky, full-width wrapper
   and the nav carries the background - which is why the safe-area padding has
   to go on the nav, or page content scrolls through the status-bar band. */
.fi-topbar-ctn { position: sticky; top: 0; z-index: 30; }
.fi-topbar {
    min-height: 3.5rem;
    padding-top: var(--ph-safe-t);
    padding-inline: 1rem;
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.04);
}

/* Room for the tab bar, plus the home indicator on notched iPhones. */
.fi-main,
/* Only reserve room for the strip on pages that actually have one - it is
   suppressed during onboarding, where this would leave ~85px of dead space
   below Save. */
body:has(.ph-tabbar) .fi-page-content { padding-bottom: calc(var(--ph-tabbar-h) + var(--ph-safe-b) + 1rem) !important; }

.fi-main { padding-inline: 0.875rem !important; }

/* Page headings sit tighter on a small screen. */
.fi-header { padding-block: 0.875rem !important; }
.fi-header-heading { font-size: 1.375rem !important; line-height: 1.75rem; }

/* A page's header action is its primary call to action - "New Function Room",
   "Add room". Filament left-aligns it at its natural width; on a phone it reads
   as an afterthought beside the heading. Give it the full width. */
.fi-header-actions-ctn .fi-ac { width: 100%; }
.fi-header-actions-ctn .fi-ac .fi-btn {
    width: 100%;
    justify-content: center;
    min-height: 3rem;
}

/* Except a destructive one. Stretching "Delete" made it the biggest, reddest
   thing at the top of the edit form, above the fields it deletes. */
.fi-header-actions-ctn .fi-ac { flex-wrap: wrap; }
.fi-header-actions-ctn .fi-ac .fi-btn.fi-color-danger {
    width: auto;
    min-height: 2.5rem;
    padding-inline: 0.875rem;
    font-size: 0.875rem;
}

/* --- 2. Touch targets ----------------------------------------------------
   44px is the accepted minimum. Filament's default buttons are smaller. */

.fi-btn,
.fi-icon-btn,
.fi-ta-actions .fi-btn,
.fi-dropdown-list-item {
    min-height: 2.75rem;
    touch-action: manipulation;
}

.fi-btn { padding-inline: 1.125rem; font-size: 0.9375rem; }

/* Kill the grey flash on tap and accidental text selection on controls. */
a, button, .fi-btn, .fi-ta-row, .ph-tabbar-item {
    -webkit-tap-highlight-color: transparent;
}
.fi-btn, .ph-tabbar-item { -webkit-user-select: none; user-select: none; }

/* --- 3. Forms ------------------------------------------------------------
   Anything under 16px makes iOS Safari zoom the viewport on focus, which then
   never zooms back out. This is the single most common mobile form bug. */

.fi-input,
.fi-select-input,
.fi-textarea textarea,
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="tel"], input[type="url"],
input[type="search"], input[type="date"], select, textarea {
    font-size: 16px !important;
}

.fi-input-wrp { min-height: 2.875rem; }
.fi-fo-field-wrp { margin-bottom: 0.25rem; }
.fi-fo-field-label { font-size: 0.875rem; font-weight: 600; }

/* Stack inline-label fields: a label beside a field is unreadable at 390px. */
.fi-fo-field-has-inline-label .fi-fo-field-label-col,
.fi-fo-field-has-inline-label .fi-fo-field-content-col {
    grid-column: span 3 / span 3 !important;
}

/* Checkbox and radio rows are the worst tap targets Filament ships: the box
   itself is 16px and the row around it only 24px, against a 44px guideline.
   The <input> sits inside its <label>, so the whole row already toggles it -
   it just needs to be tall enough to hit. This matters most on venue details
   and room details, where a venue ticks a dozen occasion and facility boxes. */
.fi-fo-checkbox-list-option,
.fi-fo-radio-option {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    min-height: 2.75rem;
    padding-block: 0.25rem;
}

/* Grow the control itself too, so it is visible as well as hittable. */
.fi-fo-checkbox-list-option .fi-checkbox-input,
.fi-fo-radio-option .fi-radio-input,
.fi-fo-field-wrp .fi-checkbox-input {
    width: 1.25rem;
    height: 1.25rem;
    flex-shrink: 0;
}

/* The text column stops the row collapsing when an option wraps to two lines. */
.fi-fo-checkbox-list-option-text { line-height: 1.3; }

/* Filament centres a 36px input inside a 46px wrapper, so the bottom 10px of
   a field looks tappable but does not focus it. Let the input fill its wrapper. */
.fi-input-wrp .fi-input,
.fi-input-wrp .fi-select-input { min-height: 2.75rem; }

/* Two columns, but only where two columns read well. A room form was four
   screens of lonely full-width number boxes with a 24px gutter between each.
   Every field spans the full width by default; the short numeric ones
   (capacities, room hire, minimum spend) pair up. */
/* Only the grid that DIRECTLY holds form fields. Matching every .fi-sc.fi-grid
   also caught the wrappers around it, and each level halved the width again. */
.fi-sc.fi-grid:has(> .fi-grid-col > .fi-sc-component > .fi-fo-field) {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
}

.fi-sc.fi-grid.fi-sc-has-gap { gap: 0.875rem !important; }

/* Only inside a form grid. Unscoped, this also spanned the dashboard's stat
   cards across both columns and put them back to one per row. */
.fi-sc.fi-grid:has(> .fi-grid-col > .fi-sc-component > .fi-fo-field) > .fi-grid-col {
    grid-column: span 2 / span 2;
}

/* The child combinators matter: without them this matches every ancestor that
   merely contains a number somewhere, and each level halves the width. */
.fi-sc.fi-grid > .fi-grid-col:has(> .fi-sc-component > .fi-fo-field input[type="number"]) {
    grid-column: span 1 / span 1;
    /* Bottom-align the pair: the grid row stretches both columns to the same
       height, so pushing the field to the end lines the two inputs up even when
       one label wraps to a second line and the other does not. */
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}

.fi-sc.fi-grid > .fi-grid-col:has(> .fi-sc-component > .fi-fo-field input[type="number"]) .fi-fo-field-label-col {
    /* Reserve two lines. "Fri Night Room Hire" takes one and "Fri Night Minimum
       Spend" takes two, which otherwise offsets the two boxes by 20px. */
    min-height: 2.5em;
}

.fi-sc.fi-grid > .fi-grid-col:has(> .fi-sc-component > .fi-fo-field input[type="number"]) .fi-fo-field-label {
    font-size: 0.8125rem;
    line-height: 1.25;
}


/* --- 4. Sections ---------------------------------------------------------
   Edge-to-edge cards read better than inset boxes on a narrow screen. */

.fi-section {
    border-radius: 0.875rem;
    box-shadow: 0 1px 3px rgb(0 0 0 / 0.06);
}
.fi-section-content { padding: 1rem !important; }
.fi-section-header { padding: 1rem 1rem 0 !important; }
.fi-section-header-heading { font-size: 1rem !important; }

/* --- 5. Tables become cards ---------------------------------------------
   A horizontally scrolling table is the worst thing on a phone. Each row is
   turned into a stacked card, with the column name shown as a small label. */

.fi-ta-ctn { border-radius: 0.875rem; }
.fi-ta-table thead { display: none; }
.fi-ta-table, .fi-ta-table tbody, .fi-ta-row, .fi-ta-cell { display: block; width: 100%; }

.fi-ta-row {
    padding: 0.875rem 1rem;
    border-bottom: 1px solid rgb(0 0 0 / 0.07);
}
.fi-ta-row:last-child { border-bottom: 0; }

.fi-ta-cell {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.1875rem 0 !important;
    text-align: right;
    border: 0 !important;
}

/* Filament pads the inner text wrapper for a desktop table row (16px/12px).
   Inside a card that doubles every row's height, so strip it back. */
.fi-ta-cell .fi-ta-col > *,
.fi-ta-cell .fi-ta-text,
.fi-ta-cell .fi-ta-text-item { padding: 0 !important; }

/* Values used to sit against their labels instead of the card's right edge.
   .fi-ta-col is flex (so justify-content works) but .fi-ta-text-item is
   display: -webkit-box for Filament's line clamp, where justify-content does
   nothing - that one needs text-align. Both, so label and value read as two
   clean columns the way the reference card does. */
.fi-ta-cell[data-ph-label] .fi-ta-col { justify-content: flex-end; }
.fi-ta-cell[data-ph-label] .fi-ta-text,
.fi-ta-cell[data-ph-label] .fi-ta-text-item { text-align: right; }
.fi-ta-cell .fi-ta-col { min-height: 0 !important; }

/* An empty toolbar still draws a blank panel above the first card.
   Tagged by venue-mobile.js rather than :has(), so it does not depend on
   selector support or on the toolbar's internal markup. */
.fi-ta-header-toolbar.ph-empty { display: none !important; }

/* The column heading, injected from the cell's own data attribute. */
.fi-ta-cell::before {
    content: attr(data-ph-label);
    flex: 0 0 auto;
    margin-right: auto;
    text-align: left;
    font-size: 0.75rem;
    font-weight: 600;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.fi-ta-cell:not([data-ph-label])::before { content: none; }

/* --- 5b. Card hierarchy and iconography ----------------------------------
   A flat stack of label/value rows reads like a spreadsheet. Give the card a
   headline, a chip for the match score beside it, an icon per row so the eye
   can find the date or the price without reading, and real weight on the
   price - which is the number the whole decision turns on. */

.fi-ta-row {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: 0.75rem;
    align-items: center;
}

/* Every cell spans the card by default; the two below opt out. */
.fi-ta-cell { grid-column: 1 / -1; }

/* The first column is the headline: big, left aligned, no label above it. */
.fi-ta-row .fi-ta-cell:first-of-type {
    grid-column: 1;
    grid-row: 1;
    padding-top: 0 !important;
    padding-bottom: 0.5rem !important;
    text-align: left;
}
.fi-ta-row .fi-ta-cell:first-of-type::before { content: none; }
.fi-ta-row .fi-ta-cell:first-of-type .fi-ta-col { justify-content: flex-start; }
.fi-ta-row .fi-ta-cell:first-of-type .fi-ta-text,
.fi-ta-row .fi-ta-cell:first-of-type .fi-ta-text-item { text-align: left; }
.fi-ta-row .fi-ta-cell:first-of-type .fi-ta-text-item {
    font-weight: 700;
    font-size: 1.0625rem;
    letter-spacing: -0.01em;
    color: #111827;
}

/* Match score rides beside the headline as a chip rather than a labelled row. */
.fi-ta-cell[data-ph-label="Match %"] {
    grid-column: 2;
    grid-row: 1;
    padding-bottom: 0.5rem !important;
}
.fi-ta-cell[data-ph-label="Match %"]::before { content: none; }
.fi-ta-cell[data-ph-label="Match %"] .fi-ta-text-item {
    display: inline-flex;
    align-items: center;
    padding: 0.1875rem 0.5rem !important;
    border-radius: 999px;
    background: rgb(124 58 237 / 0.1);
    color: var(--ph-purple-700);
    font-size: 0.75rem;
    font-weight: 700;
}

/* A hairline under the headline separates it from the detail rows. */
.fi-ta-row .fi-ta-cell:first-of-type,
.fi-ta-cell[data-ph-label="Match %"] { border-bottom: 1px solid rgb(0 0 0 / 0.06) !important; }
.fi-ta-cell[data-ph-label]:not([data-ph-label="Match %"]) { padding-top: 0.3125rem !important; }

/* Room cards have no headline column worth promoting, so keep their first cell
   on its own line rather than squeezed beside an empty second column. */
.fi-ta-row:not(:has([data-ph-label="Match %"])) .fi-ta-cell:first-of-type { grid-column: 1 / -1; }

/* An icon per row. Sized and spaced off the label, which keeps the existing
   label/value alignment intact. */
.fi-ta-cell[data-ph-label]::before {
    padding-left: 1.25rem;
    background-repeat: no-repeat;
    background-position: left center;
    background-size: 0.875rem 0.875rem;
}

.fi-ta-cell[data-ph-label="Guests"]::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.9' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z'/%3E%3C/svg%3E"); }
.fi-ta-cell[data-ph-label="Suburb"]::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.9' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M15 10.5a3 3 0 11-6 0 3 3 0 016 0z M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z'/%3E%3C/svg%3E"); }
.fi-ta-cell[data-ph-label="Date"]::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.9' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5'/%3E%3C/svg%3E"); }
.fi-ta-cell[data-ph-label="Expires"]::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.9' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z'/%3E%3C/svg%3E"); }
.fi-ta-cell[data-ph-label="Price"]::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.9' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M12 6v12m-3-2.818l.879.659c1.171.879 3.07.879 4.242 0 1.172-.879 1.172-2.303 0-3.182C13.536 12.219 12.768 12 12 12c-.725 0-1.45-.22-2.003-.659-1.106-.879-1.106-2.303 0-3.182s2.9-.879 4.006 0l.415.33M21 12a9 9 0 11-18 0 9 9 0 0118 0z'/%3E%3C/svg%3E"); }
.fi-ta-cell[data-ph-label="Capacity"]::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.9' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0z'/%3E%3C/svg%3E"); }
.fi-ta-cell[data-ph-label="Style"]::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.9' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008z'/%3E%3C/svg%3E"); }

/* A status belongs beside the thing it describes, not in a label/value row of
   its own. The icon stays in the DOM for screen readers; the pill is the
   visible form. */
.fi-ta-cell[data-ph-label="Is active"] {
    grid-column: 2;
    grid-row: 1;
    justify-content: flex-end;
    padding-bottom: 0.5rem !important;
    border-bottom: 1px solid rgb(0 0 0 / 0.06) !important;
}
.fi-ta-cell[data-ph-label="Is active"]::before { content: none; }
.fi-ta-cell[data-ph-label="Is active"] .fi-ta-icon {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
}
.fi-ta-cell[data-ph-label="Is active"]::after {
    padding: 0.1875rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 700;
}
.fi-ta-cell.ph-status-on::after {
    content: "Active";
    background: rgb(21 128 61 / 0.12);
    color: #15803d;
}
.fi-ta-cell.ph-status-off::after {
    content: "Paused";
    background: rgb(0 0 0 / 0.06);
    color: #6b7280;
}

/* Edit is the action; Delete should not match it stroke for stroke. The extra
   class is deliberate: the blanket "flex: 1 1 8rem" on these actions is defined
   further down the file and wins at equal specificity. */
.fi-ta-cell .fi-ta-actions .fi-link.fi-color-primary,
.fi-ta-cell .fi-ta-actions .fi-link.fi-color-success { flex: 1 1 60% !important; }
.fi-ta-cell .fi-ta-actions .fi-link.fi-color-danger {
    flex: 0 1 auto !important;
    border-color: transparent;
    font-weight: 500;
}

/* The price is the decision. Give it the weight the rest of the rows do not. */
.fi-ta-cell[data-ph-label="Price"] .fi-ta-text-item {
    font-size: 1.125rem;
    font-weight: 700;
    color: #111827;
}

/* A lead about to expire is the one worth acting on, so say so in colour.
   Tagged by venue-mobile.js, which reads the rendered "in 2 days" text. */
.fi-ta-cell.ph-urgent .fi-ta-text-item { color: #b45309; font-weight: 700; }
.fi-ta-cell.ph-urgent::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='2' stroke='%23b45309'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z'/%3E%3C/svg%3E");
    color: #b45309;
}

/* Row actions become real buttons at the foot of the card. Filament renders them
   as small coloured links, which is a 20px tap target buried in a list. Colour
   semantics are kept: a success or primary action fills, a destructive one does
   not, so Delete never looks like the thing you are meant to press. */
.fi-ta-cell .fi-ta-actions {
    width: 100%;
    margin-top: 0.625rem;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.fi-ta-cell .fi-ta-actions .fi-ac-link-action,
.fi-ta-cell .fi-ta-actions .fi-link {
    flex: 1 1 8rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    min-height: 2.75rem;
    padding-inline: 1rem;
    border: 1px solid currentColor;
    border-radius: 0.625rem;
    font-size: 0.9375rem;
    font-weight: 600;
    text-decoration: none;
}
/* Filament sets align-self: baseline on the label, which beats the container's
   align-items: center. Harmless at its own link height, but these are raised to
   a 44px tap target, and the label then sits about 10px above the middle of the
   button while the icons stay centred. */
.fi-ta-cell .fi-ta-actions .fi-link-label,
.fi-sc-actions .fi-link-label,
.fi-ac .fi-link-label { align-self: center; }

.fi-ta-cell .fi-ta-actions .fi-color-success,
.fi-ta-cell .fi-ta-actions .fi-color-primary {
    background: var(--ph-purple-600);
    border-color: var(--ph-purple-600);
    color: #fff !important;
}
.fi-ta-cell .fi-ta-actions .fi-color-success .fi-icon,
.fi-ta-cell .fi-ta-actions .fi-color-primary .fi-icon { color: #fff !important; }
.fi-ta-cell .fi-ta-actions .fi-color-danger { color: #b91c1c !important; background: transparent; }

/* Row actions become a full-width button row at the foot of the card. */
.fi-ta-cell:has(> .fi-ta-actions) { padding-top: 0.75rem !important; }
.fi-ta-actions {
    width: 100%;
    justify-content: stretch;
    gap: 0.5rem;
}
.fi-ta-actions .fi-btn { flex: 1 1 0; justify-content: center; }
.fi-ta-actions::before { content: none !important; }

/* The payment banner repeats on every screen until a card is added, and at
   214px it was taking a quarter of the phone. Same words, same action, about
   half the height. */
.payment-method-setup-banner {
    margin-block: 0.75rem 1rem !important;
    padding: 0.75rem 0.875rem !important;
    border-left-width: 4px !important;
}
.payment-method-setup-banner p,
.payment-method-setup-banner div { font-size: 0.8125rem; line-height: 1.4; }
.payment-method-setup-banner .fi-btn,
.payment-method-setup-banner a[class*="rounded"] {
    min-height: 2.5rem;
    padding-inline: 0.875rem;
    font-size: 0.875rem;
}

/* A search box above "No purchased leads" is a control with nothing to act on. */
.fi-ta-ctn:has(.fi-ta-empty-state) .fi-ta-header-toolbar { display: none; }

/* Toolbar: search gets its own full-width row above the filters. */
/* 121px of chrome to hold a 46px search field. */
.fi-ta-header-toolbar { flex-wrap: wrap; gap: 0.5rem; padding: 0.625rem 0.75rem !important; }
.fi-ta-search-field { flex: 1 1 100%; }
.fi-ta-search-field .fi-input { font-size: 16px !important; }

.fi-ta-empty-state { padding-block: 2.5rem !important; }

/* --- 6. Modals slide up from the bottom, like a native sheet ------------- */

/* The container is a grid of 1fr / auto / 1fr with the window in row 2, so the
   window is centred by its rows and align-self on the window has nothing to
   move within. Drop the trailing row and the 1rem gutter and it really does
   sit on the bottom edge. */
.fi-modal > .fi-modal-window-ctn {
    grid-template-rows: 1fr auto !important;
    align-items: end;
    padding: 0 !important;
}

/* The strip must not sit over an open modal, even below it: Filament's modal
   container is z-40 and comes EARLIER in the document than the strip, which a
   BODY_END hook appends to <body>. At equal z-index the later element wins, and
   because the footer actions are column-reverse the bottom-most control is the
   confirm button - so a venue tapping "Purchase lead" would have hit "Credits". */
body:has(.fi-modal-open) .ph-tabbar { display: none; }

.fi-modal-window {
    margin: 0 !important;
    max-width: 100% !important;
    width: 100% !important;
    border-radius: 1.125rem 1.125rem 0 0 !important;
    align-self: end;
    padding-bottom: var(--ph-safe-b);
    animation: ph-sheet-up 0.22s cubic-bezier(0.32, 0.72, 0, 1);
}
@keyframes ph-sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .fi-modal-window { animation: none; } }

.fi-modal-footer-actions { flex-direction: column-reverse; gap: 0.5rem; }
.fi-modal-footer-actions .fi-btn { width: 100%; justify-content: center; }

/* --- 7. A fixed Save bar --------------------------------------------------
   position: sticky cannot work on .fi-sc-actions: its containing block is the
   wrapping .fi-sc-component, whose height is the actions box itself, so the
   offset range is zero and it never leaves its static position. Filament's own
   sticky actions solve this by fixing the INNER .fi-ac, which is what this
   does - permanently, which is what a phone app does anyway, so Save is never
   below the fold on a long venue or room form.

   Scoped to the form actions by id: the onboarding pages carry a second
   schema Actions component, and styling both gives two stacked white bars. */

.fi-sc-actions[id$="form-actions"] {
    /* The bar is drawn by the fixed child now; this is just a spacer so the
       form does not jump when the child leaves the flow. */
    min-height: 3.25rem;
}

.fi-sc-actions[id$="form-actions"] .fi-ac {
    position: fixed;
    left: 0;
    right: 0;
    /* Sit on the bottom edge by default. Registration, password reset and the
       onboarding pages have no icon strip, and offsetting for one there leaves
       a dead 68px gap under the primary button. */
    bottom: var(--ph-safe-b);
    /* Above the page, below the strip (30) and far below modals (40). */
    z-index: 25;
    width: 100%;
    /* Row, not stacked: two stacked 48px buttons plus the strip eat a quarter
       of the screen. row-reverse keeps the submit button on the right, where
       Filament puts it, and nearest the thumb. */
    flex-direction: row-reverse;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: 0.625rem 0.875rem;
    background: #fff;
    border-top: 1px solid rgb(0 0 0 / 0.08);
    box-shadow: 0 -2px 10px rgb(0 0 0 / 0.06);
}

.fi-sc-actions[id$="form-actions"] .fi-btn {
    justify-content: center;
    min-height: 3rem;
    font-size: 1rem;
}

/* Submit takes the room; anything secondary stays just wide enough to read. */
.fi-sc-actions[id$="form-actions"] .fi-btn[type="submit"] { flex: 1 1 auto; }
.fi-sc-actions[id$="form-actions"] .fi-btn:not([type="submit"]) { flex: 0 0 auto; }

/* Only clear the strip on pages that actually have one. */
body:has(.ph-tabbar) .fi-sc-actions[id$="form-actions"] .fi-ac {
    bottom: calc(var(--ph-tabbar-h) + var(--ph-safe-b));
}

/* Reserve room for the bar itself, with or without the strip, or it covers the
   last field. Simple pages (registration, password reset) use fi-simple-main. */
body:has(.fi-sc-actions[id$="form-actions"]) .fi-page-content,
body:has(.fi-sc-actions[id$="form-actions"]) .fi-simple-main {
    padding-bottom: calc(var(--ph-safe-b) + 5.5rem) !important;
}

body:has(.ph-tabbar):has(.fi-sc-actions[id$="form-actions"]) .fi-page-content {
    padding-bottom: calc(var(--ph-tabbar-h) + var(--ph-safe-b) + 5.5rem) !important;
}

/* --- 8. Stats: two across, not four ------------------------------------- */

/* .fi-wi-stats-overview is the widget wrapper, a block-level grid ITEM - the
   actual grid is the .fi-grid inside it, which otherwise falls back to its
   one-column default because the container never hits Filament's @xl breakpoint. */
/* Only the stats grid itself. The widget wraps it in a second .fi-grid, and
   splitting that one too squeezes each card to 63px with the value clipped. */
.fi-wi-stats-overview .fi-section-content.fi-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 0.625rem !important;
}
.fi-wi-stats-overview-stat { padding: 0.875rem !important; border-radius: 0.875rem; }
.fi-wi-stats-overview-stat-value { font-size: 1.25rem !important; }
.fi-wi-stats-overview-stat-label { font-size: 0.75rem !important; }

/* --- 9. Login, register and other simple pages -------------------------- */

.fi-simple-main {
    width: 100%;
    max-width: 100%;
    margin: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 1.25rem 1.125rem calc(1.5rem + var(--ph-safe-b)) !important;
    min-height: 100dvh;
}
.fi-simple-layout { padding: 0 !important; background: #fff; }
.fi-simple-page-content .fi-btn { width: 100%; justify-content: center; min-height: 3rem; }
.fi-logo, .fi-logo img { height: 56px !important; }

/* --- 10. Bottom tab bar -------------------------------------------------- */

.ph-tabbar {
    display: flex;
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 30;
    height: calc(var(--ph-tabbar-h) + var(--ph-safe-b));
    padding-bottom: var(--ph-safe-b);
    background: rgb(255 255 255 / 0.94);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    backdrop-filter: saturate(180%) blur(12px);
    border-top: 1px solid rgb(0 0 0 / 0.08);
}

.ph-tabbar-item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.1875rem;
    padding-top: 0.5rem;
    color: #6b7280;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    position: relative;
}
.ph-tabbar-item svg { width: 1.5rem; height: 1.5rem; }
.ph-tabbar-item[aria-current="page"] { color: var(--ph-purple-600); }
.ph-tabbar-item[aria-current="page"]::after {
    content: "";
    position: absolute;
    top: 0;
    width: 1.75rem;
    height: 3px;
    border-radius: 0 0 3px 3px;
    background: var(--ph-purple-600);
}
.ph-tabbar-item:active { background: rgb(124 58 237 / 0.06); }

/* Count badge, for leads waiting to be bought. */
.ph-tabbar-badge {
    position: absolute;
    top: 0.3125rem;
    left: 50%;
    margin-left: 0.3125rem;
    min-width: 1.125rem;
    height: 1.125rem;
    padding-inline: 0.25rem;
    border-radius: 999px;
    background: #dc2626;
    color: #fff;
    font-size: 0.625rem;
    line-height: 1.125rem;
    text-align: center;
}

/* --- 11. Odds and ends --------------------------------------------------- */

/* Never let a wide element force the page to scroll sideways. */
/* overflow-x: hidden on body makes body a scroll container, which stops every
   position: sticky descendant from ever sticking - including the top bar, now
   the only place the brand and the user menu live. clip does not do that. */
html { max-width: 100%; overflow-x: clip; }
body { max-width: 100%; }

/* Notifications clear the tab bar. */
.fi-no { bottom: calc(var(--ph-tabbar-h) + var(--ph-safe-b) + 0.5rem) !important; }

/* Breadcrumbs waste a line on a phone. */
.fi-breadcrumbs { display: none; }

/* Momentum scrolling inside any remaining scroll area. */
.fi-ta-ctn, .fi-modal-content { -webkit-overflow-scrolling: touch; }


/* --- 12. "More" sheet ----------------------------------------------------- */

.ph-sheet-backdrop {
    position: fixed;
    inset: 0;
    z-index: 31;
    background: rgb(0 0 0 / 0.4);
}

.ph-sheet {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 32;
    background: #fff;
    border-radius: 1.125rem 1.125rem 0 0;
    padding: 0.5rem 0.75rem calc(0.75rem + var(--ph-safe-b));
    box-shadow: 0 -8px 30px rgb(0 0 0 / 0.18);
    transition: transform 0.22s cubic-bezier(0.32, 0.72, 0, 1);
}
.ph-sheet-closed { transform: translateY(100%); }
@media (prefers-reduced-motion: reduce) { .ph-sheet { transition: none; } }

.ph-sheet-grip {
    width: 2.25rem;
    height: 0.25rem;
    margin: 0.375rem auto 0.75rem;
    border-radius: 999px;
    background: #d1d5db;
}

.ph-sheet-item {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    width: 100%;
    min-height: 3.25rem;
    padding: 0 0.75rem;
    border: 0;
    border-radius: 0.75rem;
    background: transparent;
    color: #1b1b18;
    font-size: 1rem;
    font-weight: 500;
    text-align: left;
    text-decoration: none;
}
.ph-sheet-item svg { width: 1.375rem; height: 1.375rem; color: var(--ph-purple-600); flex: 0 0 auto; }
.ph-sheet-item:active { background: rgb(124 58 237 / 0.08); }
.ph-sheet-item-danger { color: #b91c1c; }
.ph-sheet-item-danger svg { color: #b91c1c; }

.ph-sheet-cancel {
    width: 100%;
    min-height: 3rem;
    margin-top: 0.5rem;
    border: 0;
    border-radius: 0.75rem;
    background: #f3f4f6;
    color: #374151;
    font-size: 1rem;
    font-weight: 600;
}

[x-cloak] { display: none !important; }


/* --- 13. Top bar brand ----------------------------------------------------
   Hiding the sidebar also hid the logo, leaving a tall empty bar. Put a
   compact wordmark back on the left and tighten the bar to match. */

.ph-topbar-brand { display: flex; align-items: center; }
.ph-topbar-brand img {
    height: 1.75rem;
    width: auto;
    max-width: 10rem;
    object-fit: contain;
}

/* The panel sets a 75px logo for the sidebar; the top bar needs far less. */
.fi-topbar .fi-logo, .fi-topbar .fi-logo img { height: 1.75rem !important; }

.fi-topbar-start { gap: 0.5rem; }
.fi-topbar-ctn, .fi-topbar { min-height: 3.25rem !important; height: auto !important; }

/* Global search is a poor fit on a phone and eats the whole bar. */
.fi-topbar .fi-global-search { display: none; }


/* --- 14. Tabs ------------------------------------------------------------
   Billing has four tabs. Stacked they push the content below the fold; wrapped
   they reflow on every tap. A horizontally scrolling strip of pills keeps them
   on one line and keeps the content where the thumb expects it. */

.fi-tabs {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.375rem;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding: 0.25rem;
    scroll-snap-type: x proximity;
}
.fi-tabs::-webkit-scrollbar { display: none; }

.fi-tabs-item {
    flex: 0 0 auto;
    min-height: 2.75rem;
    padding-inline: 0.9375rem;
    border-radius: 999px;
    font-size: 0.875rem;
    font-weight: 600;
    white-space: nowrap;
    scroll-snap-align: start;
}
/* Filament insets a contained tab panel by 24px a side. Stacked with the
   page padding, the section padding and the card padding, a phone lost 38% of
   its width to nesting and the credit buttons shrank to match. */
.fi-sc-tabs-tab { padding-inline: 0.5rem !important; }

.fi-tabs-item.fi-active { background: var(--ph-purple-600); color: #fff; }
.fi-tabs-item.fi-active .fi-tabs-item-label { color: #fff; }

/* --- 16. Infolists (purchased lead details) ------------------------------- */

.fi-in .fi-grid { grid-template-columns: repeat(1, minmax(0, 1fr)) !important; }
.fi-in-entry { padding-block: 0.375rem; }
.fi-in-entry-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em; color: #6b7280; }

/* A phone number or email in a venue's own record should be tappable. */
.fi-in-text a[href^="tel:"], .fi-in-text a[href^="mailto:"] { text-decoration: underline; }

/* --- 17. Pagination ------------------------------------------------------- */

.fi-pagination { flex-wrap: wrap; gap: 0.5rem; justify-content: center; }
.fi-pagination-items { order: -1; width: 100%; justify-content: center; }
.fi-pagination .fi-btn, .fi-pagination-item-btn { min-height: 2.5rem; min-width: 2.5rem; }


/* --- 15. Dark mode ------------------------------------------------------
   The panel ships dark mode (the provider sets a dark brand logo), so every
   surface added above needs a dark counterpart. Without these a venue on a
   dark phone gets a white strip and a white sheet against a near-black
   portal, and the 12px card labels - which are what say which number is the
   price - fall to about 3:1 contrast. */

/* Tab bar and More sheet: dark mode comes from venue-app.css's tokens. */

.dark .fi-sc-actions[id$="form-actions"] .fi-ac {
    background: #18181b;
    border-top-color: rgb(255 255 255 / 0.08);
}

/* Card labels carry the meaning on a phone, so they need real contrast. */
.dark .fi-ta-cell::before,
.dark .fi-in-entry-label { color: #a1a1aa; }

.dark .fi-ta-row .fi-ta-cell:first-of-type .fi-ta-text-item,
.dark .fi-ta-cell[data-ph-label="Price"] .fi-ta-text-item { color: #f4f4f5; }
.dark .fi-ta-cell[data-ph-label="Match %"] .fi-ta-text-item {
    background: rgb(167 139 250 / 0.18);
    color: var(--ph-purple-400);
}
.dark .fi-ta-row .fi-ta-cell:first-of-type,
.dark .fi-ta-cell[data-ph-label="Match %"] { border-bottom-color: rgb(255 255 255 / 0.08) !important; }
.dark .fi-ta-cell.ph-urgent .fi-ta-text-item { color: #fbbf24; }
.dark .fi-ta-cell.ph-status-on::after { background: rgb(74 222 128 / 0.16); color: #4ade80; }
.dark .fi-ta-cell.ph-status-off::after { background: rgb(255 255 255 / 0.08); color: #a1a1aa; }
.dark .fi-ta-cell[data-ph-label="Is active"] { border-bottom-color: rgb(255 255 255 / 0.08) !important; }


/* --- 17. Checkbox chips, dark (registration) ------------------------------ */
.dark .fi-fo-checkbox-list-option {
    background: #18181b;
    border-color: rgb(255 255 255 / 0.14);
}

} /* end max-width: 767px */
