/* /Components/Admin/AdminLayout.razor.rz.scp.css */
/* The admin shell — same glass primitives as the business panel, a distinct
   accent so it never looks like a tenant's own screen. */

.admin-rail[b-18fpxk1cbj] {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 232px;
    display: flex;
    flex-direction: column;
    background: var(--glass-bg);
    backdrop-filter: blur(18px) saturate(140%);
    -webkit-backdrop-filter: blur(18px) saturate(140%);
    border-right: 1px solid var(--glass-border);
    box-shadow: 6px 0 22px -8px var(--accent-glow-soft);
    z-index: 100;
}

.admin-brand[b-18fpxk1cbj] {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 58px;
    padding: 0 18px;
    border-bottom: 1px solid var(--glass-border);
}

/* Pomegranate, not the tenant blue — the one visual cue that this rail is the
   platform's, not a salon's. */
.admin-mark[b-18fpxk1cbj] {
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: var(--radius-sm);
    background: linear-gradient(135deg, #d45a50, #b4372f);
    box-shadow: 0 0 18px rgba(180, 55, 47, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.25);
    font-weight: 800;
    font-size: 13px;
    color: #fff;
}

.admin-brand-name[b-18fpxk1cbj] { font-size: 13px; font-weight: 700; color: var(--text-main); }
.admin-brand-sub[b-18fpxk1cbj] {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #E88A84;
    margin-top: 1px;
}

.admin-nav[b-18fpxk1cbj] { flex: 1; overflow-y: auto; padding: 12px 8px; display: flex; flex-direction: column; gap: 2px; }

.admin-nav-item[b-18fpxk1cbj] {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 11px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 500;
    color: var(--text-dim);
    text-decoration: none;
    border-left: 2px solid transparent;
    transition: 0.15s;
}

.admin-nav-item:hover[b-18fpxk1cbj] { background: var(--glass-bg-soft); color: var(--text-main); }

.admin-nav-item.active[b-18fpxk1cbj] {
    background: linear-gradient(90deg, rgba(180, 55, 47, 0.18), rgba(180, 55, 47, 0.04));
    color: var(--text-main);
    border-left-color: #B4372F;
}

.admin-nav-icon[b-18fpxk1cbj] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    font-size: 13px;
    opacity: 0.8;
}

.admin-foot[b-18fpxk1cbj] {
    padding: 12px 8px;
    border-top: 1px solid var(--glass-border);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.admin-signout[b-18fpxk1cbj] {
    width: 100%;
    text-align: left;
    padding: 8px 11px;
    font: inherit;
    font-size: 12.5px;
    color: var(--text-faint);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: 0.15s;
}

.admin-signout:hover[b-18fpxk1cbj] { color: #FCA5A5; background: rgba(180, 55, 47, 0.12); }

.admin-main[b-18fpxk1cbj] { margin-left: 232px; min-height: 100vh; }
.admin-content[b-18fpxk1cbj] { padding: 22px 24px; }

@media (max-width: 900px) {
    .admin-rail[b-18fpxk1cbj] {
        position: static;
        width: 100%;
        flex-direction: row;
        align-items: center;
        flex-wrap: wrap;
        border-right: none;
        border-bottom: 1px solid var(--glass-border);
        padding: 8px 12px;
    }
    .admin-brand[b-18fpxk1cbj] { border-bottom: none; height: auto; padding: 0; }
    .admin-nav[b-18fpxk1cbj] { flex: 1 1 100%; flex-direction: row; flex-wrap: wrap; padding: 0; }
    .admin-foot[b-18fpxk1cbj] { border-top: none; flex-direction: row; padding: 0; margin-left: auto; }
    .admin-main[b-18fpxk1cbj] { margin-left: 0; }
    .admin-content[b-18fpxk1cbj] { padding: 14px 12px; }
}
/* /Components/Admin/NumberPicker.razor.rz.scp.css */
/* The buy-box / num-list classes are GLOBAL (app.css), shared with the tenant
   detail page's copy of this flow — only the modal's paragraphs need scoping. */
.confirm[b-rhrd3gpvua] {
    font-size: 13px;
    line-height: 1.55;
    margin: 0 0 10px;
}
/* /Components/Admin/OnboardingAgentStep.razor.rz.scp.css */
/* Language tabs above the instruction box. One box, one language at a time —
   six side-by-side textareas would each be too narrow to read a paragraph in. */
.lang-tabs[b-xinb29aipc] {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 8px;
}

.lang-tab[b-xinb29aipc] {
    position: relative;
    appearance: none;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    padding: 7px 13px;
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.lang-tab:hover[b-xinb29aipc] {
    color: var(--text-main);
}

.lang-tab.is-on[b-xinb29aipc] {
    border-color: var(--accent-glow);
    background: var(--accent-glow-soft);
    color: var(--text-main);
}

/* A dot on every language that has been written, so an admin sees which of the
   six are done without opening each tab in turn. */
.lang-tab.has-text[b-xinb29aipc]::after {
    content: "";
    position: absolute;
    top: 5px;
    right: 5px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--color-success);
}

.area[b-xinb29aipc] {
    resize: vertical;
    min-height: 260px;
    /* Read as a block of prose and edited line by line — a proportional face
       makes the "never do this" list hard to scan. */
    font-family: ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;
    font-size: 12.5px;
    line-height: 1.6;
}

/* Farsi and Arabic need their own line height — the monospace stack above has
   no Persian glyphs, so those tabs fall back to a system face. */
.area[dir="rtl"][b-xinb29aipc] {
    font-family: Vazirmatn, "Segoe UI", Tahoma, sans-serif;
    font-size: 13.5px;
    line-height: 1.9;
}
/* /Components/Admin/OnboardingFinishStep.razor.rz.scp.css */
/* The readiness checklist. Deliberately shows every line, ticked or not, rather
   than only what's missing — an admin about to put a real business on a real
   phone line should see the whole list they are signing off. */
/* Splits the checklist into "yours" and "the owner's". Without the heading an
   admin reads eight items as eight things they forgot, and goes looking for
   screens this wizard doesn't have. */
.ready-group[b-jd348dr6ps] {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-dim);
    margin: 0 0 8px;
}

.ready-group + .ready-list[b-jd348dr6ps] {
    margin-bottom: 18px;
}

.ready-list[b-jd348dr6ps] {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
    font-size: 13px;
}

.ready-list li[b-jd348dr6ps] {
    display: flex;
    align-items: center;
    gap: 9px;
}

/* Same probe rows as the test step; scoped CSS doesn't cross components. */
.probe-list[b-jd348dr6ps] {
    list-style: none;
    margin: 10px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.probe[b-jd348dr6ps] {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 11px 12px;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    background: var(--glass-bg-soft);
}

.probe-name[b-jd348dr6ps] {
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 2px;
}

.probe-why[b-jd348dr6ps] {
    font-size: 12px;
    line-height: 1.5;
}

/* A provisioning failure. Given more weight than an ordinary alert because it
   sits next to a green "is live" banner that is itself true — the business IS
   active on our side — and the admin has to come away knowing the phone line
   still answers nothing. */
.prov-fail[b-jd348dr6ps] {
    border-left-width: 4px;
    border-left-style: solid;
}

.prov-why[b-jd348dr6ps] {
    margin-top: 7px;
    font-size: 12.5px;
    line-height: 1.55;
    opacity: .92;
}

/* The CallixCore payload. Monospace and wide: it is JSON that gets copied
   whole, and a proportional wrap makes it look like prose to be edited. */
.area.mono[b-jd348dr6ps] {
    resize: vertical;
    font-family: ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;
    font-size: 12px;
    line-height: 1.5;
    white-space: pre;
    overflow-x: auto;
}
/* /Components/Admin/OnboardingOwnerStep.razor.rz.scp.css */
/* Scoped copy — .readonly lives in the Settings page's own scoped CSS, so the
   markup would render bare here without it. */
.readonly[b-ri0hynsnsp] {
    padding: 9px 11px;
    border: 1px dashed var(--glass-border);
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    color: var(--text-faint);
    font-size: 12.5px;
}
/* /Components/Admin/OnboardingTestStep.razor.rz.scp.css */
/* One row per probe: a verdict badge, then what it means in a full sentence.
   The sentence is the point — an admin who has just filled in eight forms needs
   to know what to do next, not what our enum is called. */
.probe-list[b-83j5tjd63s] {
    list-style: none;
    margin: 16px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.probe[b-83j5tjd63s] {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 11px 12px;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    background: var(--glass-bg-soft);
}

.probe-name[b-83j5tjd63s] {
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 2px;
}

.probe-why[b-83j5tjd63s] {
    font-size: 12px;
    line-height: 1.5;
}
/* /Components/Admin/WizardSteps.razor.rz.scp.css */
/* The step rail. Scrolls horizontally on a narrow screen rather than wrapping
   into a second row that reads as a second wizard. */
.wiz-rail[b-l59d125bpg] {
    display: flex;
    align-items: stretch;
    gap: 4px;
    margin: 0 0 22px;
    padding: 0;
    list-style: none;
    overflow-x: auto;
    scrollbar-width: thin;
}

.wiz-step[b-l59d125bpg] {
    flex: 1 1 0;
    min-width: 108px;
}

.wiz-hit[b-l59d125bpg] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    width: 100%;
    height: 100%;
    padding: 12px 6px 11px;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    font: inherit;
    font-size: 12px;
    text-align: center;
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}

/* A step that can't be opened yet must not look pressable. */
.wiz-hit.is-static[b-l59d125bpg] {
    cursor: default;
}

.wiz-hit:not(.is-static):hover[b-l59d125bpg] {
    background: var(--glass-bg);
    color: var(--text-main);
}

.wiz-dot[b-l59d125bpg] {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
}

.wiz-label[b-l59d125bpg] {
    line-height: 1.25;
}

.is-done .wiz-dot[b-l59d125bpg] {
    border-color: color-mix(in srgb, var(--color-success) 55%, transparent);
    background: color-mix(in srgb, var(--color-success) 20%, transparent);
    color: var(--color-success);
}

.is-current .wiz-hit[b-l59d125bpg] {
    border-color: var(--accent-glow);
    background: var(--accent-glow-soft);
    color: var(--text-main);
}

.is-current .wiz-dot[b-l59d125bpg] {
    border-color: var(--accent-glow);
    background: var(--accent-gradient);
    color: var(--accent-text-on-fill);
}

.is-todo .wiz-hit[b-l59d125bpg] {
    color: var(--text-faint);
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
/* Shell: fixed glass rail + topbar, content scrolling beneath.
   Layout follows the supplied dashboard template; colours are Avacallix's. */

.sidebar[b-fe1kw3848b] {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--sidebar-w);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border-right: 1px solid var(--glass-border);
    /* Cast to the right only. A plain 0 0 25px glow throws light out of all four
       sides, and the rail is pinned to the edges on three of them — so most of
       it lands on the content instead, hazing the column beside the rail. */
    box-shadow: 6px 0 22px -8px var(--accent-glow-soft);
    display: flex;
    flex-direction: column;
    z-index: 100;
}

.sidebar-brand[b-fe1kw3848b] {
    height: var(--nav-h);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 18px;
    border-bottom: 1px solid var(--glass-border);
    flex-shrink: 0;
}

/* The same mark as the login card — one brand, one mark.
 *
 * No background, no gradient and no inset highlight, unlike the lettered box it
 * replaced: the artwork carries its own gold gradient and a transparent
 * surround, so painting a themed square behind it would show as a coloured
 * rectangle poking out from under the glyph.
 *
 * NOTE: the source PNG had to be de-hazed to make that true. The master logo
 * ships with a near-white wash (RGB~246 at alpha up to 74) over the whole
 * canvas; carried into the icon it rendered as a pale square behind the mark on
 * a dark rail, which is indistinguishable from a CSS background and was
 * reported as one. See brand/README.md — do not regenerate these by a plain
 * crop.
 *
 * The glow is kept, and kept THEMED. It sits outside the artwork rather than
 * behind it, so the mark still belongs to the blue and lilac palettes instead
 * of floating as a gold sticker — the one thing a fixed-colour logo risks in a
 * five-theme UI.
 */
.brand-mark[b-fe1kw3848b] {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    object-fit: contain;
    filter: drop-shadow(0 0 7px var(--accent-glow));
}

.brand-name[b-fe1kw3848b] { font-size: 13px; font-weight: 700; }

.brand-sub[b-fe1kw3848b] {
    font-size: 10px;
    color: var(--ink-dim);
    margin-top: 1px;
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------- Nav ---------- */

.sidebar-nav[b-fe1kw3848b] {
    flex: 1;
    overflow-y: auto;
    padding: 10px 8px;
}

.sidebar-nav[b-fe1kw3848b]::-webkit-scrollbar { width: 3px; }
.sidebar-nav[b-fe1kw3848b]::-webkit-scrollbar-thumb { background: var(--glass-edge); border-radius: 3px; }

.nav-label[b-fe1kw3848b] {
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 1px;
    color: var(--ink-faint);
    text-transform: uppercase;
    padding: 12px 10px 5px;
}

/* ::deep — NavLink renders its own <a>, which scoped CSS can't reach. */
.sidebar-nav[b-fe1kw3848b]  .nav-item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 11px;
    border-radius: var(--r-sm);
    font-size: 13px;
    font-weight: 500;
    color: var(--ink-dim);
    cursor: pointer;
    transition: 0.15s;
    margin-bottom: 1px;
    text-decoration: none;
    border-left: 2px solid transparent;
}

.sidebar-nav[b-fe1kw3848b]  .nav-item:hover {
    background: var(--glow-soft);
    color: var(--ink);
}

/* The active page is lit from its leading edge — faster to read than colour
   alone, and it survives being colour-blind. */
.sidebar-nav[b-fe1kw3848b]  .nav-item.active {
    background: linear-gradient(90deg, rgba(78, 134, 224, 0.18), rgba(78, 134, 224, 0.04));
    color: var(--accent2);
    border-left-color: var(--saffron);
    box-shadow: 0 0 10px rgba(78, 134, 224, 0.1);
}

/* Emoji and geometric glyphs mix here, and they have very different metrics —
   a fixed box keeps the labels aligned whichever the glyph is. */
.sidebar-nav[b-fe1kw3848b]  .nav-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    font-size: 13px;
    line-height: 1;
    opacity: 0.75;
    flex-shrink: 0;
}

.sidebar-nav[b-fe1kw3848b]  .nav-item.active .nav-icon { opacity: 1; }

.sidebar-nav[b-fe1kw3848b]  .nav-badge {
    margin-left: auto;
    background: rgba(78, 134, 224, 0.2);
    border: 1px solid rgba(78, 134, 224, 0.35);
    color: var(--accent2);
    font-size: 9.5px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 20px;
}

/* ---------- Footer ---------- */

.sidebar-footer[b-fe1kw3848b] {
    padding: 12px;
    border-top: 1px solid var(--glass-edge);
}

.user-card[b-fe1kw3848b] {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 10px;
    border-radius: var(--r-sm);
    background: var(--glow-soft);
}

.user-av[b-fe1kw3848b] {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    flex-shrink: 0;
    background: linear-gradient(135deg, var(--lajvard), var(--accent));
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 12px;
    color: #F4F8FF;
}

.user-text[b-fe1kw3848b] { min-width: 0; }

.user-name[b-fe1kw3848b] {
    font-size: 12px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.user-role[b-fe1kw3848b] { font-size: 10px; color: var(--ink-dim); }

.signout[b-fe1kw3848b] { margin-left: auto; display: flex; }

.signout-btn[b-fe1kw3848b] {
    background: none;
    border: none;
    color: var(--ink-faint);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    transition: 0.15s;
}

.signout-btn:hover[b-fe1kw3848b] { color: var(--crit); background: rgba(248, 113, 113, 0.1); }

/* ---------- Topbar ---------- */

.topbar[b-fe1kw3848b] {
    position: fixed;
    top: 0;
    left: var(--sidebar-w);
    right: 0;
    height: var(--nav-h);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border-bottom: 1px solid var(--glass-border);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 20px;
    z-index: 90;
}

.topbar-actions[b-fe1kw3848b] { display: flex; align-items: center; gap: 6px; }

.tb-action[b-fe1kw3848b] {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    border: 1px solid var(--glass-edge);
    background: rgba(255, 255, 255, 0.03);
    color: var(--ink-dim);
    transition: 0.15s;
    white-space: nowrap;
    text-decoration: none;
}

.tb-action:hover[b-fe1kw3848b] {
    background: var(--glow-soft);
    color: var(--accent2);
    border-color: rgba(78, 134, 224, 0.3);
    text-decoration: none;
}

.tb-action.primary[b-fe1kw3848b] {
    background: linear-gradient(135deg, rgba(233, 161, 59, 0.22), rgba(233, 161, 59, 0.1));
    color: var(--saffron-soft);
    border-color: rgba(233, 161, 59, 0.35);
    box-shadow: 0 0 14px rgba(233, 161, 59, 0.12);
}

.tb-action.primary:hover[b-fe1kw3848b] {
    color: var(--saffron-soft);
    box-shadow: 0 0 20px rgba(233, 161, 59, 0.22);
}

.topbar-div[b-fe1kw3848b] { width: 1px; height: 22px; background: var(--glass-edge); margin: 0 4px; }
.topbar-spacer[b-fe1kw3848b] { flex: 1; }

/* ROOM FOR THE ASSISTANT BUTTON, which is position:fixed and therefore invisible
   to this flex row. Without it the plan badge sits under the button: both are
   right-aligned, and the badge has no idea anything is there.
   Kept in step with .help-trigger's own width by eye — the button is icon (30) +
   gap (7) + a short word, plus its own padding. */
.topbar[b-fe1kw3848b] { padding-inline-end: 150px; }

@media (max-width: 720px) {
    /* The word is hidden at this width, so the button shrinks to its icon. */
    .topbar[b-fe1kw3848b] { padding-inline-end: 62px; }
}

/* Minutes against the plan cap — the number that decides the month's margin. */
.sub-badge[b-fe1kw3848b] {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border-radius: 20px;
    background: rgba(78, 134, 224, 0.1);
    border: 1px solid rgba(78, 134, 224, 0.25);
    font-size: 11px;
    font-weight: 600;
    color: var(--accent2);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.sub-dot[b-fe1kw3848b] {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--ok);
    box-shadow: 0 0 5px rgba(74, 222, 128, 0.6);
}

/* ---------- Main ---------- */

.main[b-fe1kw3848b] {
    margin-left: var(--sidebar-w);
    padding-top: var(--nav-h);
    min-height: 100vh;
    position: relative;
    z-index: 1;
}

/* NOTE: `position:relative; z-index:1` above makes .main a STACKING CONTEXT,
   which traps `position:fixed` overlays inside it. The escape hatch for that
   lives in app.css (`html[data-overlay] .main`) — it cannot live here, because
   scoped CSS can neither match <html> nor override with the same specificity. */

.content[b-fe1kw3848b] { padding: 20px 22px; }

@media (max-width: 900px) {
    .sidebar[b-fe1kw3848b] {
        position: static;
        width: 100%;
        height: auto;
        flex-direction: row;
        align-items: center;
        border-right: none;
        border-bottom: 1px solid var(--glass-edge);
        flex-wrap: wrap;
        padding: 8px 12px;
        gap: 10px;
    }

    .sidebar-brand[b-fe1kw3848b] { border-bottom: none; padding: 0; }
    .sidebar-nav[b-fe1kw3848b] { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 4px; padding: 0; }
    .sidebar-nav[b-fe1kw3848b]  .nav-item { border-left: none; border-bottom: 2px solid transparent; }
    .sidebar-nav[b-fe1kw3848b]  .nav-item.active { border-left: none; border-bottom-color: var(--saffron); }
    .nav-label[b-fe1kw3848b] { display: none; }
    .sidebar-footer[b-fe1kw3848b] { border-top: none; padding: 0; margin-left: auto; }

    .topbar[b-fe1kw3848b] { position: static; left: 0; height: auto; padding: 8px 12px; flex-wrap: wrap; }
    .topbar-div[b-fe1kw3848b] { display: none; }
    .main[b-fe1kw3848b] { margin-left: 0; padding-top: 0; }
    .content[b-fe1kw3848b] { padding: 14px 12px; }
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-uvwgvi223c],
.components-reconnect-repeated-attempt-visible[b-uvwgvi223c],
.components-reconnect-failed-visible[b-uvwgvi223c],
.components-pause-visible[b-uvwgvi223c],
.components-resume-failed-visible[b-uvwgvi223c],
.components-rejoining-animation[b-uvwgvi223c] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-retrying[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-failed[b-uvwgvi223c],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-uvwgvi223c] {
    display: block;
}


#components-reconnect-modal[b-uvwgvi223c] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-uvwgvi223c 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-uvwgvi223c 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-uvwgvi223c 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-uvwgvi223c]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-uvwgvi223c 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-uvwgvi223c {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-uvwgvi223c {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-uvwgvi223c {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-uvwgvi223c] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-uvwgvi223c] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-uvwgvi223c] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-uvwgvi223c] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-uvwgvi223c] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-uvwgvi223c] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-uvwgvi223c] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-uvwgvi223c 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-uvwgvi223c] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-uvwgvi223c {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Modules/RenewalBanner.razor.rz.scp.css */
/* Amber, in-flow, dismissible — a nudge above the module content, not a modal
   that stops work. It sits inside the page it warns about. */
.renewal[b-xe1ydku77b] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 14px;
    margin-bottom: 14px;
    background: rgba(233, 161, 59, 0.1);
    border: 1px solid rgba(233, 161, 59, 0.3);
    border-radius: var(--radius-md);
}

.renewal-text[b-xe1ydku77b] { font-size: 12.5px; line-height: 1.5; color: var(--text-dim); }
.renewal-text strong[b-xe1ydku77b] { color: var(--text-main); font-weight: 600; }

.renewal-actions[b-xe1ydku77b] { display: flex; align-items: center; gap: 6px; flex: none; }

/* The dismiss ✕ is quiet — the renew button is the action, this is the escape. */
.renewal-x[b-xe1ydku77b] {
    color: var(--text-faint);
    background: transparent;
    border-color: transparent;
}

.renewal-x:hover[b-xe1ydku77b] { color: var(--text-main); background: rgba(255, 255, 255, 0.06); }
/* /Components/Pages/Admin/AdminDashboard.razor.rz.scp.css */
/* ---- Platform dashboard tiles ----
   Scoped, not added to app.css: `.stat` there is shared by other admin pages,
   and widening it would restyle screens this change never looked at.

   Every tint is layered OVER the theme's own --glass-bg-soft rather than painted
   opaque. app.css is explicit that a literal colour is a bug, because the panel
   ships three themes (blue / gold / lilac) and an opaque tile would stay navy on
   the other two. */

.kpi-grid[b-to4zzne73j] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
    gap: 10px;
}

.kpi[b-to4zzne73j] {
    position: relative;
    overflow: hidden;
    padding: 12px 13px;
    border-radius: var(--radius-md, 10px);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    min-width: 0;
    transition: transform 0.18s;
}

.kpi:hover[b-to4zzne73j] { transform: translateY(-2px); }

/* The lit top edge that says "glass" rather than "coloured rectangle". */
.kpi[b-to4zzne73j]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-edge-lit) 45%, transparent);
    pointer-events: none;
    z-index: 1;
}

/* The corner bloom carrying each tile's hue, set per-tint via --k-bloom. */
.kpi[b-to4zzne73j]::after {
    content: "";
    position: absolute;
    top: -22px;
    right: -22px;
    width: 68px;
    height: 68px;
    border-radius: 50%;
    background: var(--k-bloom, transparent);
    filter: blur(20px);
    pointer-events: none;
}

.kpi-icon[b-to4zzne73j] {
    position: absolute;
    top: 9px;
    right: 10px;
    font-size: 14px;
    opacity: 0.45;
    z-index: 1;
    pointer-events: none;
}

.kpi-lbl[b-to4zzne73j] {
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding-right: 20px;
    position: relative;
    z-index: 1;
}

.kpi-val[b-to4zzne73j] {
    font-size: 21px;
    font-weight: 800;
    color: var(--text-main);
    line-height: 1.2;
    margin-top: 3px;
    position: relative;
    z-index: 1;
}

.kpi-unit[b-to4zzne73j] { font-size: 11px; font-weight: 600; color: var(--text-dim); margin-left: 3px; }

.kpi-sub[b-to4zzne73j] {
    font-size: 10.5px;
    color: var(--text-dim);
    margin-top: 3px;
    position: relative;
    z-index: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.kpi-val.faint[b-to4zzne73j] { color: var(--text-faint); }
.warn-txt[b-to4zzne73j] { color: var(--warn, #E9A13B); }

/* ---- Tints ---- */

.k-blue[b-to4zzne73j]   { background: linear-gradient(160deg, rgba(78,134,224,.16), var(--glass-bg-soft)); border-color: rgba(78,134,224,.30); --k-bloom: rgba(78,134,224,.22); }
.k-green[b-to4zzne73j]  { background: linear-gradient(160deg, rgba(74,222,128,.14), var(--glass-bg-soft)); border-color: rgba(74,222,128,.30); --k-bloom: rgba(74,222,128,.20); }
.k-cyan[b-to4zzne73j]   { background: linear-gradient(160deg, rgba(34,211,238,.14), var(--glass-bg-soft)); border-color: rgba(34,211,238,.30); --k-bloom: rgba(34,211,238,.20); }
.k-indigo[b-to4zzne73j] { background: linear-gradient(160deg, rgba(129,140,248,.15), var(--glass-bg-soft)); border-color: rgba(129,140,248,.30); --k-bloom: rgba(129,140,248,.20); }
.k-pink[b-to4zzne73j]   { background: linear-gradient(160deg, rgba(244,114,182,.14), var(--glass-bg-soft)); border-color: rgba(244,114,182,.30); --k-bloom: rgba(244,114,182,.20); }
.k-teal[b-to4zzne73j]   { background: linear-gradient(160deg, rgba(45,212,191,.14), var(--glass-bg-soft)); border-color: rgba(45,212,191,.30); --k-bloom: rgba(45,212,191,.20); }
.k-red[b-to4zzne73j]    { background: linear-gradient(160deg, rgba(248,113,113,.14), var(--glass-bg-soft)); border-color: rgba(248,113,113,.30); --k-bloom: rgba(248,113,113,.20); }
.k-slate[b-to4zzne73j]  { background: linear-gradient(160deg, rgba(148,163,184,.10), var(--glass-bg-soft)); border-color: rgba(148,163,184,.26); --k-bloom: rgba(148,163,184,.14); }

/* Money IN — the brand saffron, the same hue revenue wears everywhere else in
   the product. */
.k-gold[b-to4zzne73j] {
    background: linear-gradient(160deg, rgba(233,161,59,.20), var(--glass-bg-soft));
    border-color: rgba(233,161,59,.40);
    --k-bloom: rgba(233,161,59,.28);
}

/* Money OUT — violet, deliberately nothing like the saffron above. The two sit
   near each other and confusing spend with revenue is the one mistake this
   dashboard must not invite. */
.k-purple[b-to4zzne73j] {
    background: linear-gradient(160deg, rgba(167,139,250,.17), var(--glass-bg-soft));
    border-color: rgba(167,139,250,.34);
    --k-bloom: rgba(167,139,250,.24);
}

/* ---- Section headings ---- */
.sec-head[b-to4zzne73j] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 4px 10px;
    margin: 20px 0 9px;
}

.sec-title[b-to4zzne73j] {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-dim);
}

.sec-note[b-to4zzne73j] { font-size: 10.5px; color: var(--text-faint); }

/* ---- Budget meter ---- */
.budget[b-to4zzne73j] {
    margin-top: 10px;
    padding: 11px 13px;
    border-radius: var(--radius-md, 10px);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
}

.budget-head[b-to4zzne73j] {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    font-size: 11.5px;
    color: var(--text-dim);
    margin-bottom: 7px;
}

.budget-bar[b-to4zzne73j] {
    height: 8px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.06);
    overflow: hidden;
}

.budget-fill[b-to4zzne73j] {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, rgba(167,139,250,.85), rgba(129,140,248,.85));
    transition: width 0.3s ease;
}

/* Past the budget the bar turns red — the point at which the number stops being
   informational and starts being a decision. */
.budget-fill.over[b-to4zzne73j] {
    background: linear-gradient(90deg, rgba(248,113,113,.9), rgba(233,161,59,.9));
}

/* ---- Per-model token table ---- */
.model-rows[b-to4zzne73j] { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }

.model-row[b-to4zzne73j] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 10px;
    align-items: baseline;
    font-size: 11.5px;
}

.model-name[b-to4zzne73j] {
    color: var(--text-main);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.model-toks[b-to4zzne73j] { color: var(--text-dim); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---- Collapsed audit trail ----
   A disclosure rather than a deletion: the trail is the record of every change
   made with power over every business, and removing it outright is the kind of
   thing that is regretted the first time something needs explaining. */
.trail[b-to4zzne73j] { margin-top: 22px; }

.trail > summary[b-to4zzne73j] {
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-dim);
    padding: 9px 12px;
    border-radius: var(--radius-md, 10px);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    list-style: none;
    user-select: none;
}

.trail > summary[b-to4zzne73j]::-webkit-details-marker { display: none; }

/* The caret is drawn rather than relying on the native marker, which differs
   between browsers and is hidden above. */
.trail > summary[b-to4zzne73j]::before {
    content: "▸";
    display: inline-block;
    margin-right: 7px;
    transition: transform 0.15s;
    color: var(--text-faint);
}

.trail[open] > summary[b-to4zzne73j]::before { transform: rotate(90deg); }
.trail > summary:hover[b-to4zzne73j] { color: var(--text-main); }
.trail-body[b-to4zzne73j] { margin-top: 10px; }

/* ---- Configuration health ----
 *
 * Sits above the money figures because a finding here changes how those figures
 * should be read: an empty price book means the caps shown are not the ones
 * being applied, and an undecryptable Stripe key means the revenue line is not
 * being collected at all.
 *
 * Tinted over --glass-bg-soft like the KPI cards above, so it belongs to the
 * page rather than looking bolted on. Literal rgba rather than a token: there is
 * no --danger in this theme (verified), and a var() typo would fall through to
 * an untinted panel — which on the one element that says "something is broken"
 * is the failure that matters most.
 */

.health-panel[b-to4zzne73j] {
    border: 1px solid;
    border-radius: var(--radius-lg);
    padding: 13px 16px;
    margin-bottom: 18px;
}

.hp-crit[b-to4zzne73j] {
    background: linear-gradient(160deg, rgba(180, 55, 47, .18), var(--glass-bg-soft));
    border-color: rgba(255, 138, 138, .42);
}

.hp-warn[b-to4zzne73j] {
    background: linear-gradient(160deg, rgba(233, 161, 59, .14), var(--glass-bg-soft));
    border-color: rgba(233, 161, 59, .36);
}

.health-title[b-to4zzne73j] {
    font-weight: 700;
    font-size: 13.5px;
    margin-bottom: 8px;
}

.hp-crit .health-title[b-to4zzne73j] { color: var(--text-error); }
.hp-warn .health-title[b-to4zzne73j] { color: #F5C97B; }

.health-list[b-to4zzne73j] {
    margin: 0;
    padding-left: 18px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 12.5px;
    line-height: 1.5;
}

/* The area name leads, so the list can be scanned for the subsystem rather than
   read sentence by sentence. */
.health-list strong[b-to4zzne73j] {
    margin-right: 5px;
}

.hf-crit strong[b-to4zzne73j] { color: var(--text-error); }
.hf-warn strong[b-to4zzne73j] { color: #F5C97B; }
/* /Components/Pages/Admin/AdminPricing.razor.rz.scp.css */
/* The price book.
 *
 * Laid out as one block per plan rather than a wide table. Nine columns of
 * fixed-width number boxes came to roughly 900px and pushed the card into a
 * horizontal scroll — which on a FORM is the worst kind, because the Save button
 * ends up off-screen from the field being edited.
 *
 * Every colour is a theme token: the panel runs three themes and a literal hex
 * is right in one and wrong in the other two.
 */

.plan-list[b-h0v4ejlh0w] {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 4px 16px 16px;
}

.plan[b-h0v4ejlh0w] {
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    background: var(--glass-bg-soft);
    padding: 14px 16px;
    /* Belt and braces: nothing inside may push the block wider than the card. */
    min-width: 0;
}

/* ---- Name and actions ---- */

.plan-top[b-h0v4ejlh0w] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.plan-name[b-h0v4ejlh0w] {
    display: flex;
    align-items: baseline;
    gap: 9px;
    min-width: 0;
    /* Takes the slack so the actions sit at the far edge, but shrinks first. */
    flex: 1 1 200px;
}

.plan-name .input[b-h0v4ejlh0w] {
    font-weight: 600;
    max-width: 220px;
    min-width: 0;
}

/* The enum slot behind the name. Small and dim because it is an identity, not a
   setting — it can never be edited, and tenants and payments store it. */
.slot[b-h0v4ejlh0w] {
    font-size: 10.5px;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.plan-actions[b-h0v4ejlh0w] {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: none;
}

/* ---- The figures ---- */

/* auto-fit rather than a fixed column count: six fields sit on one row on a wide
   screen and reflow to three or two as the panel narrows, with no breakpoint to
   maintain and no width at which they overflow. */
.plan-fields[b-h0v4ejlh0w] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
    gap: 10px;
}

.pf[b-h0v4ejlh0w] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.pf-label[b-h0v4ejlh0w] {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-faint);
    white-space: nowrap;
    /* A long label must not be what widens the column. */
    overflow: hidden;
    text-overflow: ellipsis;
}

/* No fixed width: the grid column decides, which is what keeps the row from
   overflowing. width:100% + min-width:0 stops a number input's default size
   attribute from setting a floor the grid then has to honour. */
.pf .input[b-h0v4ejlh0w] {
    width: 100%;
    min-width: 0;
    padding: 7px 9px;
    font-size: 13px;
}

/* ---- Add a plan ---- */

.add-plan[b-h0v4ejlh0w] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 0 16px 16px;
    font-size: 12px;
}
/* /Components/Pages/Admin/AdminPrompts.razor.rz.scp.css */
/* Library beside editor. The list is the narrow column: it is scanned, while
   the editor is read and typed into. */
.prompt-cols[b-jme3mps578] {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    gap: 18px;
    align-items: start;
}

/* One column below a tablet — 300px of list plus a prose textarea does not fit
   a phone, and the editor is the half that must stay usable. */
@media (max-width: 900px) {
    .prompt-cols[b-jme3mps578] {
        grid-template-columns: minmax(0, 1fr);
    }
}

.lib-card[b-jme3mps578] {
    position: sticky;
    top: 18px;
}

.lib-list[b-jme3mps578] {
    list-style: none;
    margin: 0;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-height: 70vh;
    overflow-y: auto;
}

.lib-item[b-jme3mps578] {
    display: block;
    width: 100%;
    text-align: left;
    appearance: none;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: inherit;
    font: inherit;
    padding: 9px 11px;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}

.lib-item:hover[b-jme3mps578] {
    background: var(--glass-bg-soft);
}

.lib-item.is-on[b-jme3mps578] {
    border-color: var(--accent-glow);
    background: var(--accent-glow-soft);
}

/* A hidden template stays legible rather than being greyed to the edge of
   readable — it is the one an admin is most likely to be part-way through
   rewriting, so its wording has to be easy to get back to. */
.lib-item.is-hidden .lib-name[b-jme3mps578] {
    opacity: .72;
}

.lib-name[b-jme3mps578] {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 13.5px;
    font-weight: 600;
}

.lib-desc[b-jme3mps578] {
    font-size: 11.5px;
    line-height: 1.45;
    margin-top: 3px;
}

.lib-langs[b-jme3mps578] {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 6px;
}

.lang-chip[b-jme3mps578] {
    font-size: 10.5px;
    padding: 2px 6px;
    border-radius: 999px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
}

.two-up[b-jme3mps578] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px;
}

@media (max-width: 700px) {
    .two-up[b-jme3mps578] {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Language tabs and the prose box. Both are redefined here rather than reused:
   the originals live in OnboardingAgentStep's SCOPED css, which does not cross
   components — copied markup would render unstyled. */
.lang-tabs[b-jme3mps578] {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 8px;
}

.lang-tab[b-jme3mps578] {
    position: relative;
    appearance: none;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    padding: 7px 13px;
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.lang-tab:hover[b-jme3mps578] {
    color: var(--text-main);
}

.lang-tab.is-on[b-jme3mps578] {
    border-color: var(--accent-glow);
    background: var(--accent-glow-soft);
    color: var(--text-main);
}

/* A dot on every language that has been written, so an admin sees which of the
   six are done without opening each tab in turn. */
.lang-tab.has-text[b-jme3mps578]::after {
    content: "";
    position: absolute;
    top: 5px;
    right: 5px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--color-success);
}

.area[b-jme3mps578] {
    resize: vertical;
    min-height: 320px;
    font-family: ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;
    font-size: 12.5px;
    line-height: 1.6;
}

/* Farsi and Arabic need their own face: the monospace stack above has no
   Persian glyphs, so those tabs would fall back to something unreadable. */
.area[dir="rtl"][b-jme3mps578] {
    font-family: Vazirmatn, "Segoe UI", Tahoma, sans-serif;
    font-size: 13.5px;
    line-height: 1.9;
}
/* /Components/Pages/Admin/AdminTenantDetail.razor.rz.scp.css */
/* ---- Activity & usage (admin tenant detail) ----
   Scoped rather than added to app.css: these classes exist for this one screen,
   and the admin area's shared vocabulary (.card, .badge, .tbl) is already
   global. Putting `.metric` in app.css would make a very generic name a
   platform-wide commitment. */

/* ---- The call-volume headline ---- */
.trend[b-10ss4eozpd] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    margin-bottom: 14px;
    border-radius: var(--radius-md, 10px);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    /* Same glass as the cards below it, so the banner reads as part of the
       section rather than a notice pasted above it. */
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    position: relative;
    overflow: hidden;
}

.trend[b-10ss4eozpd]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-edge-lit) 45%, transparent);
    pointer-events: none;
}

.trend-arrow[b-10ss4eozpd] { font-size: 20px; line-height: 1; }
.trend-val[b-10ss4eozpd] { font-size: 15px; font-weight: 700; color: var(--text-main); }
.trend-sub[b-10ss4eozpd] { font-size: 11.5px; color: var(--text-dim); margin-top: 2px; }

/* Direction carries a colour, but the arrow glyph and the sentence carry it
   too — the meaning never depends on colour alone. */
.trend.is-up[b-10ss4eozpd] {
    border-color: rgba(74, 222, 128, 0.35);
    background: linear-gradient(160deg, rgba(74, 222, 128, 0.10), var(--glass-bg-soft));
}
.trend.is-up .trend-arrow[b-10ss4eozpd] { color: #4ADE80; }

.trend.is-down[b-10ss4eozpd] {
    border-color: rgba(248, 113, 113, 0.35);
    background: linear-gradient(160deg, rgba(248, 113, 113, 0.10), var(--glass-bg-soft));
}
.trend.is-down .trend-arrow[b-10ss4eozpd] { color: #F87171; }

.trend.is-flat .trend-arrow[b-10ss4eozpd] { color: var(--text-faint); }

/* ---- Call-outcome breakdown ----
   The only row on this page whose parts sum to a whole, so it is drawn as one
   continuous bar: a shape that is visibly ONE thing split three ways, rather
   than three separate figures the eye might try to add to the cards below. */
.outcome[b-10ss4eozpd] {
    padding: 11px 13px;
    margin-bottom: 14px;
    border-radius: var(--radius-md, 10px);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
}

.outcome-head[b-10ss4eozpd] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    /* Wraps rather than crushing the equation on a narrow window — it is the
       point of this row, so it must never be the thing that gets clipped. */
    flex-wrap: wrap;
    gap: 4px 10px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-dim);
    margin-bottom: 8px;
}

/* The equation, shown as the proof that this row reconciles. Monospaced digits
   so "5 + 38 + 33 = 76" lines up and reads as arithmetic rather than prose. */
.outcome-note[b-10ss4eozpd] {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 700;
    color: var(--text-dim);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    flex: 0 0 auto;
}

.outcome-bar[b-10ss4eozpd] {
    display: flex;
    height: 10px;
    border-radius: 5px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.05);
}

/* flex is set inline from the counts, so the widths ARE the proportions. */
.seg[b-10ss4eozpd] { min-width: 0; transition: flex-grow 0.25s ease; }

.seg-booked[b-10ss4eozpd]    { background: rgba(74, 222, 128, 0.75); }
.seg-requested[b-10ss4eozpd] { background: rgba(233, 161, 59, 0.75); }
.seg-none[b-10ss4eozpd]      { background: rgba(148, 163, 184, 0.45); }

.outcome-keys[b-10ss4eozpd] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    margin-top: 9px;
    font-size: 11px;
    color: var(--text-dim);
}

/* Each key repeats its number in text — the bar's proportions are the shape,
   but a 3%-wide segment is unreadable on its own, and colour alone must never
   be the only carrier. */
.okey[b-10ss4eozpd] { display: flex; align-items: center; gap: 6px; }
.okey b[b-10ss4eozpd] { color: var(--text-main); font-weight: 700; }
.okey em[b-10ss4eozpd] { color: var(--text-faint); font-style: normal; font-size: 10.5px; }

.dot[b-10ss4eozpd] { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.d-booked[b-10ss4eozpd]    { background: rgba(74, 222, 128, 0.9); }
.d-requested[b-10ss4eozpd] { background: rgba(233, 161, 59, 0.9); }
.d-none[b-10ss4eozpd]      { background: rgba(148, 163, 184, 0.6); }

/* ---- The figure grid ----
   auto-fit rather than a fixed column count: this card sits full width under a
   variable-width sidebar, and a fixed six-across would either overflow on a
   laptop or leave a gulf on a wide monitor. */
.metric-grid[b-10ss4eozpd] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
}

/* Each card is real glass: blurred, with a lit top edge and a coloured bloom in
   the corner — the same treatment the Dashboard tiles and the login card use, so
   this section belongs to the product rather than looking bolted on.

   IMPORTANT: every tint below is layered OVER the theme's own --glass-bg-soft,
   never painted as an opaque colour. app.css is explicit that a literal colour
   is a bug, because the panel ships three themes (blue / gold / lilac) and an
   opaque card would stay navy on the other two. The rgba tints are translucent
   accents, so the theme's base still shows through and follows the switch. */
.metric[b-10ss4eozpd] {
    position: relative;
    overflow: hidden;
    padding: 11px 12px;
    border-radius: var(--radius-md, 10px);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    min-width: 0;
    transition: transform 0.18s, box-shadow 0.18s;
}

/* The lit top edge that says "glass" rather than "coloured rectangle". */
.metric[b-10ss4eozpd]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-edge-lit) 45%, transparent);
    pointer-events: none;
    z-index: 1;
}

/* The corner bloom carrying each card's own hue. Set per-tint below via
   --m-bloom, so this rule is written once. */
.metric[b-10ss4eozpd]::after {
    content: "";
    position: absolute;
    top: -22px;
    right: -22px;
    width: 68px;
    height: 68px;
    border-radius: 50%;
    background: var(--m-bloom, transparent);
    filter: blur(20px);
    pointer-events: none;
}

.metric:hover[b-10ss4eozpd] { transform: translateY(-2px); }

/* The icon sits in the corner behind the bloom, low-contrast: it labels the card
   at a glance without competing with the number, which is what is actually being
   read. */
.metric-icon[b-10ss4eozpd] {
    position: absolute;
    top: 9px;
    right: 10px;
    font-size: 14px;
    opacity: 0.45;
    z-index: 1;
    pointer-events: none;
}

.metric-lbl[b-10ss4eozpd] {
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    position: relative;
    z-index: 1;
    /* Clears the corner icon, so a long label truncates instead of sliding
       underneath it. */
    padding-right: 20px;
}

.metric-val[b-10ss4eozpd] {
    font-size: 20px;
    font-weight: 700;
    color: var(--text-main);
    line-height: 1.2;
    margin-top: 3px;
    position: relative;
    z-index: 1;
}

.metric-unit[b-10ss4eozpd] { font-size: 11px; font-weight: 600; color: var(--text-dim); margin-left: 3px; }

.metric-sub[b-10ss4eozpd] {
    font-size: 10.5px;
    color: var(--text-dim);
    margin-top: 3px;
    position: relative;
    z-index: 1;
}

/* ---- The tints ----
   One hue per card, so the eye can return to the same figure without re-reading
   labels. Each sets a translucent gradient, a matching border and its bloom;
   nothing is opaque, so the theme underneath still shows through.

   Colour is never the ONLY carrier of meaning here — every card also has its
   icon and its written label. */

.m-blue[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(78, 134, 224, 0.16), var(--glass-bg-soft));
    border-color: rgba(78, 134, 224, 0.3);
    --m-bloom: rgba(78, 134, 224, 0.22);
}

.m-indigo[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(129, 140, 248, 0.15), var(--glass-bg-soft));
    border-color: rgba(129, 140, 248, 0.3);
    --m-bloom: rgba(129, 140, 248, 0.2);
}

.m-cyan[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(34, 211, 238, 0.14), var(--glass-bg-soft));
    border-color: rgba(34, 211, 238, 0.3);
    --m-bloom: rgba(34, 211, 238, 0.2);
}

.m-green[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(74, 222, 128, 0.14), var(--glass-bg-soft));
    border-color: rgba(74, 222, 128, 0.3);
    --m-bloom: rgba(74, 222, 128, 0.2);
}

.m-red[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(248, 113, 113, 0.14), var(--glass-bg-soft));
    border-color: rgba(248, 113, 113, 0.3);
    --m-bloom: rgba(248, 113, 113, 0.2);
}

.m-amber[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(233, 161, 59, 0.17), var(--glass-bg-soft));
    border-color: rgba(233, 161, 59, 0.34);
    --m-bloom: rgba(233, 161, 59, 0.24);
}

.m-pink[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(244, 114, 182, 0.14), var(--glass-bg-soft));
    border-color: rgba(244, 114, 182, 0.3);
    --m-bloom: rgba(244, 114, 182, 0.2);
}

.m-teal[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(45, 212, 191, 0.14), var(--glass-bg-soft));
    border-color: rgba(45, 212, 191, 0.3);
    --m-bloom: rgba(45, 212, 191, 0.2);
}

/* Money the business paid us — the brand saffron, matching the Dashboard's
   revenue tile so the same colour means the same thing across the product. */
.m-gold[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(233, 161, 59, 0.2), var(--glass-bg-soft));
    border-color: rgba(233, 161, 59, 0.4);
    --m-bloom: rgba(233, 161, 59, 0.28);
}

/* Money we SPEND. Violet, deliberately nothing like the saffron above: the two
   cards sit near each other and confusing revenue with cost is the one mistake
   this section must not invite. */
.m-purple[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(167, 139, 250, 0.17), var(--glass-bg-soft));
    border-color: rgba(167, 139, 250, 0.34);
    --m-bloom: rgba(167, 139, 250, 0.24);
}

/* A figure we cannot source yet — grey, and deliberately the dullest card here,
   because it holds no data to look at. */
.m-slate[b-10ss4eozpd] {
    background: linear-gradient(160deg, rgba(148, 163, 184, 0.1), var(--glass-bg-soft));
    border-color: rgba(148, 163, 184, 0.26);
    --m-bloom: rgba(148, 163, 184, 0.14);
}

/* Over the plan cap. Not an error — it is overage revenue — but it must be
   impossible to miss when scanning a page of tenants. */
.metric-val.over[b-10ss4eozpd], .metric-sub .over[b-10ss4eozpd] { color: var(--crit, #F87171); }

.metric-val.faint[b-10ss4eozpd] { color: var(--text-faint); }
.warn-txt[b-10ss4eozpd] { color: var(--warn, #E9A13B); }

/* Our cost, not the tenant's — the tint itself lives on .m-purple above. This
   rule carries only what the tint cannot: a left rule marking it as a different
   KIND of figure from the revenue cards it sits beside. */
.metric-cost[b-10ss4eozpd] { box-shadow: inset 3px 0 0 rgba(167, 139, 250, 0.55); }

/* A figure we cannot source yet. Dashed, so it reads as a known gap rather
   than as a zero. */
.metric-todo[b-10ss4eozpd] { border-style: dashed; }

/* ---- Month-by-month charts ---- */
.chart-grid[b-10ss4eozpd] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 12px;
}
/* /Components/Pages/Admin/AdminTrialNumbers.razor.rz.scp.css */
/* Trial number pool.

   The stat-* classes are NOT global — they live in each page's own scoped CSS
   (Dashboard, Calls, Products all define their own copy), so a page that reuses
   the markup without them renders unstyled boxes. Copied here for that reason,
   with one addition: .stat-note, the line under each figure that says what the
   number MEANS rather than only what it counts.
*/

.stats-grid[b-5j69r8dnxg] {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin-bottom: 16px;
}
.stat-card[b-5j69r8dnxg] {
    border-radius: var(--r);
    padding: 10px 12px;              /* Dashboard uses 16px 18px */
    border: 1px solid;
    position: relative;
    overflow: hidden;
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
}
.stat-card[b-5j69r8dnxg]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-edge-lit) 45%, transparent);
    pointer-events: none;
}
.stat-card[b-5j69r8dnxg]::after {
    content: "";
    position: absolute;
    top: -18px; right: -18px;
    width: 56px; height: 56px;
    border-radius: 50%;
    filter: blur(18px);
}
.stat-val[b-5j69r8dnxg] {
    font-size: 19px;                 /* Dashboard uses 26px */
    font-weight: 800;
    color: var(--text-main);
    line-height: 1.1;
    position: relative; z-index: 1;
}
.stat-unit[b-5j69r8dnxg] { font-size: 11px; font-weight: 600; color: var(--text-dim); margin-left: 3px; }
.stat-lbl[b-5j69r8dnxg] {
    font-size: 10.5px;
    color: var(--text-dim);
    margin-top: 3px;
    position: relative; z-index: 1;
}
.stat-blue[b-5j69r8dnxg] {
    background: linear-gradient(160deg, rgba(78, 134, 224, 0.16), rgba(24, 38, 66, 0.62));
    border-color: rgba(78, 134, 224, 0.28);
}
.stat-blue[b-5j69r8dnxg]::after { background: rgba(78, 134, 224, 0.2); }

.stat-green[b-5j69r8dnxg] {
    background: linear-gradient(160deg, rgba(74, 222, 128, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(74, 222, 128, 0.26);
}
.stat-green[b-5j69r8dnxg]::after { background: rgba(74, 222, 128, 0.18); }

.stat-amber[b-5j69r8dnxg] {
    background: linear-gradient(160deg, rgba(233, 161, 59, 0.17), rgba(24, 38, 66, 0.62));
    border-color: rgba(233, 161, 59, 0.32);
}
.stat-amber[b-5j69r8dnxg]::after { background: rgba(233, 161, 59, 0.22); }

.stat-cyan[b-5j69r8dnxg] {
    background: linear-gradient(160deg, rgba(34, 211, 238, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(34, 211, 238, 0.26);
}
.stat-cyan[b-5j69r8dnxg]::after { background: rgba(34, 211, 238, 0.18); }

@media (max-width: 900px) {
    .stats-grid[b-5j69r8dnxg] { grid-template-columns: repeat(2, 1fr); }
}

/* The consequence under each figure. Deliberately quiet — it explains the
   number above it and must not compete with it for attention. */
.stat-note[b-5j69r8dnxg] {
    margin-top: 4px;
    font-size: 10.5px;
    line-height: 1.35;
    opacity: .62;
}

/* Three tiles here, not the four the other pages carry. */
.stats-grid[b-5j69r8dnxg] { grid-template-columns: repeat(3, 1fr); }

@media (max-width: 900px) {
    .stats-grid[b-5j69r8dnxg] { grid-template-columns: 1fr; }
}
/* /Components/Pages/AdvisorPricing.razor.rz.scp.css */
.page-header[b-u398kv6p9y] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.page-title[b-u398kv6p9y] { font-size: 17px; font-weight: 700; }
.page-sub[b-u398kv6p9y] { font-size: 12px; color: var(--text-dim); margin-top: 2px; max-width: 62ch; }

/* Says why they're on the wall: a lapse, not a module they never had. Amber,
   because it is a warning about their own account, not an error. */
.lapsed[b-u398kv6p9y] {
    padding: 11px 14px;
    margin-bottom: 14px;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--text-dim);
    background: rgba(233, 161, 59, 0.09);
    border: 1px solid rgba(233, 161, 59, 0.28);
    border-radius: var(--radius-md);
}

/* The one plan card — the whole decision on this page. Capped so it reads as a
   card, not a banner stretched across a wide screen. */
.plan[b-u398kv6p9y] {
    max-width: 460px;
    padding: 20px 22px;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    box-shadow: var(--shadow);
}

.plan-head[b-u398kv6p9y] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding-bottom: 14px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--glass-border);
}

.plan-name[b-u398kv6p9y] { font-size: 15px; font-weight: 700; color: var(--text-main); }
.plan-tag[b-u398kv6p9y] { font-size: 11px; color: var(--text-faint); margin-top: 2px; }

.plan-price[b-u398kv6p9y] { text-align: right; white-space: nowrap; }
.price-num[b-u398kv6p9y] { font-size: 26px; font-weight: 800; color: #F2BE72; line-height: 1; }
/* Defined HERE and not inherited: scoped CSS does not cross components, so
   PlanCards' .price-usd does nothing on this page and the label would render
   at body size beside a 26px figure. */
.price-usd[b-u398kv6p9y] { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; color: var(--text-faint); margin-left: 2px; }
.price-per[b-u398kv6p9y] { font-size: 11px; color: var(--text-faint); }

.plan-points[b-u398kv6p9y] {
    list-style: none;
    margin: 0 0 18px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.plan-points li[b-u398kv6p9y] {
    position: relative;
    padding-left: 22px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-dim);
}

/* A green check on each line — the value, ticked off. */
.plan-points li[b-u398kv6p9y]::before {
    content: "✓";
    position: absolute;
    left: 0;
    top: 0;
    color: #4ADE80;
    font-weight: 700;
}

.btn-pay[b-u398kv6p9y] { width: 100%; justify-content: center; font-size: 13.5px; padding: 10px; }

.mock-note[b-u398kv6p9y] {
    margin-top: 12px;
    font-size: 10.5px;
    line-height: 1.5;
    color: var(--text-faint);
    text-align: center;
}

.alert-error[b-u398kv6p9y] {
    padding: 9px 12px;
    margin-bottom: 12px;
    font-size: 12px;
    color: #FCA5A5;
    background: rgba(180, 55, 47, 0.14);
    border: 1px solid rgba(248, 113, 113, 0.32);
    border-radius: var(--radius-md);
}
/* /Components/Pages/AiSettings.razor.rz.scp.css */
/* AI receptionist settings — segmented language control + textarea guidance. */

.seg[b-zdovy6ma9e] {
    display: inline-flex;
    border: 1px solid var(--glass-border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--glass-bg-soft);
    margin-bottom: 6px;
}

.seg-btn[b-zdovy6ma9e] {
    appearance: none;
    border: none;
    background: transparent;
    color: var(--text-dim);
    padding: 8px 16px;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
    border-right: 1px solid var(--glass-border);
    transition: background .15s ease, color .15s ease;
}

.seg-btn:last-child[b-zdovy6ma9e] { border-right: none; }

.seg-btn:hover[b-zdovy6ma9e] { color: var(--text); }

.seg-btn.seg-on[b-zdovy6ma9e] {
    background: var(--accent, #23509B);
    color: #fff;
}

.area[b-zdovy6ma9e] { resize: vertical; min-height: 120px; }

/* ---- Shared page chrome (scoped copies of the Business page's classes) ---- */

.page-header[b-zdovy6ma9e] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}

.page-title[b-zdovy6ma9e] { font-size: 17px; font-weight: 700; }

.page-sub[b-zdovy6ma9e] {
    font-size: 12px;
    color: var(--text-faint);
    margin-top: 3px;
}

.hint[b-zdovy6ma9e] { font-size: 10.5px; }
.hint.err[b-zdovy6ma9e] { color: var(--text-error); }

.row-actions[b-zdovy6ma9e] { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
/* /Components/Pages/Billing.razor.rz.scp.css */
/* Billing — two full-width sections, each with its own coloured header band so
   they read apart at a glance. Lajvard blue for the plan (our main product),
   pomegranate for the payment ledger.

   Both span the page. The plan section holds three cards side by side and needs
   the width; putting anything beside it would squeeze the one thing the page is
   for into half a screen. */

/* Frosted-glass panel: translucent, blurred, soft depth. */
.bill-card[b-1au6opz663] {
    border: 1px solid var(--glass-border);
    border-radius: 14px;
    overflow: hidden;
    background: color-mix(in srgb, var(--glass-bg) 78%, transparent);
    backdrop-filter: blur(14px) saturate(120%);
    -webkit-backdrop-filter: blur(14px) saturate(120%);
    box-shadow: 0 8px 24px rgba(0,0,0,0.22), inset 0 1px 0 rgba(255,255,255,0.06);
    margin-bottom: 16px;
}

/* Coloured header band — glassy 3D: a colour gradient under a glass sheen, a
   soft top highlight and a bottom shadow line so it reads as a raised bar. */
.bill-head[b-1au6opz663] {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.28);
    border-bottom: 1px solid rgba(0,0,0,0.25);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.35),
                inset 0 -6px 14px rgba(0,0,0,0.18);
}
/* The glass sheen: a bright band across the top third. */
.bill-head[b-1au6opz663]::after {
    content: "";
    position: absolute; inset: 0 0 auto 0; height: 55%;
    background: linear-gradient(180deg, rgba(255,255,255,0.30), rgba(255,255,255,0));
    pointer-events: none;
}
.bill-head .head-title[b-1au6opz663] { font-weight: 700; font-size: 14px; letter-spacing: .3px; z-index: 1; }
.bill-head .head-tag[b-1au6opz663] {
    z-index: 1;
    font-size: 11px;
    background: rgba(255,255,255,0.25);
    border: 1px solid rgba(255,255,255,0.35);
    padding: 2px 10px;
    border-radius: 999px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
}

/* Plan = lajvard blue (the core product). */
.head-plan[b-1au6opz663]  { background: linear-gradient(180deg, #3a6bc4, #23509B 55%, #1c407c); }
/* Payments = pomegranate. */
.head-pay[b-1au6opz663]   { background: linear-gradient(180deg, #cf4c43, #B4372F 55%, #922c25); }

.bill-body[b-1au6opz663] { padding: 16px; }
.bill-body.no-pad[b-1au6opz663] { padding: 0; }

/* ---- 1 · The subscription window, above the cards ----

   One line: what state the subscription is in and which dates it runs between.
   The cards below answer what the plan gives and what it costs; keeping the two
   apart means neither has to carry the other's job. */
.plan-window[b-1au6opz663] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 10px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--glass-border);
}

.plan-state[b-1au6opz663] { font-size: 13px; font-weight: 700; }
.plan-state.ok[b-1au6opz663]    { color: #86EFAC; }
.plan-state.trial[b-1au6opz663] { color: #E9A13B; }
.plan-state.off[b-1au6opz663]   { color: var(--text-faint); }

.plan-dates[b-1au6opz663] { font-size: 13px; color: var(--text-dim); }
.plan-dates .arrow[b-1au6opz663] { margin: 0 6px; opacity: .6; }

/* What "Choose this plan" will do, in one sentence, under the buttons that do
   it. A plan change takes money and restarts the month, so the terms belong
   where the decision is made — not on a page the owner would have to go and
   find afterwards. */
.plan-note[b-1au6opz663] {
    margin: 6px 0 0;
    font-size: 11.5px;
    line-height: 1.6;
    text-align: center;
}

/* ---- 2 · Payments grid (full width, clickable rows) ---- */
.pay-grid[b-1au6opz663] { width: 100%; }
.pay-row[b-1au6opz663] { cursor: pointer; transition: background .12s ease; }
.pay-row:hover[b-1au6opz663] { background: var(--glass-bg-soft); }
.pay-row .chev[b-1au6opz663] { color: var(--text-faint); font-size: 18px; text-align: right; width: 20px; }

.ref[b-1au6opz663] {
    font-size: 11px;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    color: var(--text-dim);
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: 5px;
    padding: 1px 6px;
    user-select: all;
    white-space: nowrap;
}

/* ---- Detail drawer ---- */
.drawer-scrim[b-1au6opz663] {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.45);
    z-index: 40;
    animation: fade-b-1au6opz663 .15s ease;
}
.drawer[b-1au6opz663] {
    position: fixed; top: 0; right: 0; bottom: 0;
    width: min(420px, 92vw);
    background: var(--surface, #14161c);
    border-left: 1px solid var(--glass-border);
    z-index: 41;
    display: flex; flex-direction: column;
    box-shadow: -12px 0 40px rgba(0,0,0,0.4);
    animation: slidein-b-1au6opz663 .18s ease;
}
@keyframes fade-b-1au6opz663 { from { opacity: 0; } }
@keyframes slidein-b-1au6opz663 { from { transform: translateX(24px); opacity: 0; } }

.drawer-head[b-1au6opz663] {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 18px; border-bottom: 1px solid var(--glass-border);
}
.drawer-title[b-1au6opz663] { font-weight: 700; font-size: 15px; }
.drawer-x[b-1au6opz663] {
    appearance: none; border: none; background: transparent;
    color: var(--text-dim); font-size: 16px; cursor: pointer; padding: 4px;
}
.drawer-x:hover[b-1au6opz663] { color: var(--text); }
.drawer-body[b-1au6opz663] { padding: 18px; overflow-y: auto; }

.detail[b-1au6opz663] { display: grid; grid-template-columns: 96px 1fr; gap: 10px 14px; margin: 0; }
.detail dt[b-1au6opz663] { color: var(--text-faint); font-size: 12px; }
.detail dd[b-1au6opz663] { margin: 0; font-size: 13px; word-break: break-all; }
.drawer-note[b-1au6opz663] { margin-top: 18px; font-size: 11.5px; line-height: 1.6; }

/* ---- Shared page chrome ---- */
.page-header[b-1au6opz663] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
    /* Wraps rather than crushing the gauges on a narrow screen: two bars squeezed
       to thumbnail width say nothing, where a second row still reads. */
    flex-wrap: wrap;
}
.page-title[b-1au6opz663] { font-size: 17px; font-weight: 700; }
.page-sub[b-1au6opz663] { font-size: 12px; color: var(--text-faint); margin-top: 3px; }

/* ---- Header gauges: time left and minutes left ----

   Between the title and the "Manage card" button. Two small bars, read together:
   the allowance and the days it has to cover. They are deliberately quiet — the
   real meter lives on the plan card, and this pair is a glance, not the record. */
.head-gauges[b-1au6opz663] {
    display: flex;
    gap: 18px;
    /* Takes the slack in the header so the button stays hard right and the
       gauges do not drift about as the numbers change width. */
    flex: 1 1 260px;
    justify-content: flex-end;
    align-items: flex-start;
    padding-top: 2px;
}

.gauge[b-1au6opz663] {
    min-width: 108px;
    max-width: 168px;
    flex: 1 1 0;
}

.gauge-top[b-1au6opz663] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 5px;
}

.gauge-label[b-1au6opz663] {
    font-size: 10.5px;
    letter-spacing: .3px;
    text-transform: uppercase;
    color: var(--text-faint);
}

.gauge-value[b-1au6opz663] {
    font-size: 12px;
    font-weight: 700;
    color: var(--ink);
    white-space: nowrap;
}

/* Over the allowance is the one state worth colouring: it is money. */
.gauge-value.over[b-1au6opz663] { color: var(--text-error); }

.gauge-bar[b-1au6opz663] {
    height: 5px;
    border-radius: 999px;
    overflow: hidden;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
}

.gauge-fill[b-1au6opz663] {
    height: 100%;
    border-radius: 999px;
    transition: width .3s ease;
}

/* Time is the neutral one — it passes whatever anybody does. Minutes are the
   figure the owner can act on, so they carry the brand blue. */
.fill-time[b-1au6opz663] { background: var(--text-faint); }
.fill-mins[b-1au6opz663] { background: #23509B; }
.fill-over[b-1au6opz663] { background: var(--text-error); }

@media (max-width: 700px) {
    /* On its own row the pair reads left-to-right like the rest of the page,
       rather than hugging the right edge under the title. */
    .head-gauges[b-1au6opz663] { justify-content: flex-start; flex-basis: 100%; }
}
/* /Components/Pages/Calls.razor.rz.scp.css */
/* ---- Header tiles ----
   The stat-* classes live in Dashboard's scoped CSS, so they never reached this
   page and the cards rendered unstyled. Redefined here, deliberately smaller:
   the subject of /calls is the table, not the header. */
.stats-grid[b-71d6s35wpz] {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin-bottom: 16px;
}

.stat-card[b-71d6s35wpz] {
    border-radius: var(--r);
    padding: 10px 12px;              /* Dashboard uses 16px 18px */
    border: 1px solid;
    position: relative;
    overflow: hidden;
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
}

/* The lit top edge, as on every other surface. */
.stat-card[b-71d6s35wpz]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-edge-lit) 45%, transparent);
    pointer-events: none;
}

/* The corner bloom that gives each tile its tint. */
.stat-card[b-71d6s35wpz]::after {
    content: "";
    position: absolute;
    top: -18px; right: -18px;
    width: 56px; height: 56px;
    border-radius: 50%;
    filter: blur(18px);
}

.stat-val[b-71d6s35wpz] {
    font-size: 19px;                 /* Dashboard uses 26px */
    font-weight: 800;
    color: var(--text-main);
    line-height: 1.1;
    position: relative; z-index: 1;
}
.stat-unit[b-71d6s35wpz] { font-size: 11px; font-weight: 600; color: var(--text-dim); margin-left: 3px; }
.stat-lbl[b-71d6s35wpz] {
    font-size: 10.5px;
    color: var(--text-dim);
    margin-top: 3px;
    position: relative; z-index: 1;
}

/* Each tint layered over the same navy glass base, never over black. */
.stat-blue[b-71d6s35wpz] {
    background: linear-gradient(160deg, rgba(78, 134, 224, 0.16), rgba(24, 38, 66, 0.62));
    border-color: rgba(78, 134, 224, 0.28);
}
.stat-blue[b-71d6s35wpz]::after { background: rgba(78, 134, 224, 0.2); }

.stat-green[b-71d6s35wpz] {
    background: linear-gradient(160deg, rgba(74, 222, 128, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(74, 222, 128, 0.26);
}
.stat-green[b-71d6s35wpz]::after { background: rgba(74, 222, 128, 0.18); }

.stat-amber[b-71d6s35wpz] {
    background: linear-gradient(160deg, rgba(233, 161, 59, 0.17), rgba(24, 38, 66, 0.62));
    border-color: rgba(233, 161, 59, 0.32);
}
.stat-amber[b-71d6s35wpz]::after { background: rgba(233, 161, 59, 0.22); }

.stat-cyan[b-71d6s35wpz] {
    background: linear-gradient(160deg, rgba(34, 211, 238, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(34, 211, 238, 0.26);
}
.stat-cyan[b-71d6s35wpz]::after { background: rgba(34, 211, 238, 0.18); }

@media (max-width: 900px) {
    .stats-grid[b-71d6s35wpz] { grid-template-columns: repeat(2, 1fr); }
}

/* ---- Detail drawer ----
   Matches the Billing drawer, but wider: this one holds a conversation, and a
   narrow column turns a 37-turn call into an unreadable ribbon. */
/* Above the layout chrome. MainLayout pins the sidebar at z-index 100 and the
   topbar at 90; at the Billing drawer's 40/41 this panel slid UNDER both, so
   its header — the date and the only close button — was painted over by the
   topbar and looked missing. */
.drawer-scrim[b-71d6s35wpz] {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.45);
    z-index: 200;
    animation: fade-b-71d6s35wpz .15s ease;
}
.drawer[b-71d6s35wpz] {
    position: fixed; top: 0; right: 0; bottom: 0;
    width: min(640px, 96vw);
    /* The page gradient underneath the theme's own glass — NOT a hard-coded
       colour. --surface does not exist in this theme, so the old
       `var(--surface, #14161c)` silently fell through to a navy that ignored
       the gold and lilac themes, and left the panel see-through enough that the
       table behind it showed through the header. */
    background: var(--bg-gradient);
    border-left: 1px solid var(--glass-border);
    z-index: 201;
    display: flex; flex-direction: column;
    box-shadow: -12px 0 40px rgba(0,0,0,0.4);
    animation: slidein-b-71d6s35wpz .18s ease;
}
@keyframes fade-b-71d6s35wpz { from { opacity: 0; } }
@keyframes slidein-b-71d6s35wpz { from { transform: translateX(24px); opacity: 0; } }

/* Pinned: the header must never be squeezed or scrolled away by a long
   transcript — it carries the date, the length and the only close button.
   Without flex-shrink:0 a 37-turn call collapses it on a short screen. */
.drawer-head[b-71d6s35wpz] {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 16px 18px; border-bottom: 1px solid var(--glass-border);
    flex: 0 0 auto;
    background: var(--bg-gradient);
}
.drawer-title[b-71d6s35wpz] { font-weight: 700; font-size: 15px; }
.drawer-x[b-71d6s35wpz] {
    appearance: none; border: none; background: transparent;
    color: var(--text-dim); font-size: 16px; cursor: pointer; padding: 4px;
}
.drawer-x:hover[b-71d6s35wpz] { color: var(--text); }
/* min-height:0 is what actually lets this scroll. A flex child defaults to
   min-height:auto, so it refuses to shrink below its content and the transcript
   pushes the drawer instead of scrolling inside it. */
.drawer-body[b-71d6s35wpz] { padding: 18px; overflow-y: auto; flex: 1 1 auto; min-height: 0; }

.detail[b-71d6s35wpz] { display: grid; grid-template-columns: 92px 1fr; gap: 10px 14px; margin: 0; }
.detail dt[b-71d6s35wpz] { color: var(--text-faint); font-size: 12px; }
.detail dd[b-71d6s35wpz] { margin: 0; font-size: 13px; }
.drawer-note[b-71d6s35wpz] { margin-top: 18px; font-size: 11.5px; line-height: 1.6; }

.sec-title[b-71d6s35wpz] {
    font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
    color: var(--text-faint); margin-bottom: 12px; font-weight: 700;
}
/* Sticks to the top of the scrolling body, so a long transcript never leaves
   you wondering which section you are in. */
.convo-head[b-71d6s35wpz] {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    position: sticky; top: -18px;          /* cancels .drawer-body padding */
    background: var(--bg-gradient);
    padding: 6px 0; margin-top: 22px; z-index: 2;
}
.convo-count[b-71d6s35wpz] { text-transform: none; letter-spacing: 0; font-weight: 600; opacity: .75; }

/* Sits where a player would, so the absence is stated rather than implied. */
.no-audio[b-71d6s35wpz] {
    display: flex; align-items: center; gap: 9px;
    padding: 9px 12px; margin-bottom: 10px;
    border-radius: var(--r-sm);
    border: 1px dashed var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text-faint);
    font-size: 11.5px; line-height: 1.5;
}
.no-audio-icon[b-71d6s35wpz] { font-size: 14px; opacity: .8; flex: 0 0 auto; }

/* ---- Conversation ----
   Sits on the same navy glass as every other surface, rather than the flat
   panel background, so the transcript reads as a pane of the theme and not a
   pasted-in box. Caller and receptionist are also offset left/right, so the two
   sides stay distinguishable without relying on colour alone. */
.convo[b-71d6s35wpz] {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    border-radius: var(--r);
    background: linear-gradient(160deg, rgba(35, 80, 155, 0.10), rgba(24, 38, 66, 0.55));
    border: 1px solid var(--glass-border);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
}

.turn[b-71d6s35wpz] {
    border-radius: 10px;
    padding: 9px 12px;
    max-width: 88%;
    border: 1px solid var(--glass-border);
}
.turn-who[b-71d6s35wpz] {
    font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
    color: var(--text-faint); margin-bottom: 3px; font-weight: 700;
}
.turn-text[b-71d6s35wpz] { font-size: 13px; line-height: 1.55; white-space: pre-wrap; }

/* The receptionist is the house voice: lajvard, the brand blue. */
.t-agent[b-71d6s35wpz] {
    align-self: flex-start;
    background: rgba(35, 80, 155, 0.22);
    border-color: rgba(78, 134, 224, 0.28);
}

/* The caller is phosphor green — the one thing an owner scans for when reading
   a transcript is "what did the customer actually say", so it gets the loudest
   colour on the page and a matching glow. */
.t-caller[b-71d6s35wpz] {
    align-self: flex-end;
    background: rgba(57, 255, 20, 0.14);
    border-color: rgba(57, 255, 20, 0.45);
    box-shadow: 0 0 14px rgba(57, 255, 20, 0.12);
}
.t-caller .turn-who[b-71d6s35wpz] { color: #7CFF5B; }
.t-caller .turn-text[b-71d6s35wpz] { color: #E8FFE2; }

/* ---- List ---- */
.row-click[b-71d6s35wpz] { cursor: pointer; }
.row-click:hover[b-71d6s35wpz] { background: rgba(255,255,255,0.035); }

/* A real conversation nobody wrote up. Saffron and a left edge, so it is findable
   while scrolling a hundred rows — the badge alone sits in the middle of the
   table where the eye does not sweep. Deliberately not red: the call was
   answered and the customer was served, the write-up is what went missing. */
.row-click.is-missed[b-71d6s35wpz] {
    background: rgba(233, 161, 59, 0.08);
    box-shadow: inset 3px 0 0 rgba(233, 161, 59, 0.55);
}

.row-click.is-missed:hover[b-71d6s35wpz] {
    background: rgba(233, 161, 59, 0.15);
}

/* ---- A blocked caller ----

   A DEEPER ORANGE than .is-missed, not the same saffron. The two tints sit in
   one column of rows and mean opposite things: amber is "the receptionist may
   have dropped something, go and look", this is "the system did exactly what you
   asked". If they were the same colour the owner would open blocked calls
   expecting work to do.

   Explicit rgba rather than a token: --danger does not exist in this theme, and
   the two alert tones next to this one are written the same way.  */
.row-click.is-blocked[b-71d6s35wpz] {
    background: rgba(217, 119, 47, 0.10);
    box-shadow: inset 3px 0 0 rgba(217, 119, 47, 0.75);
}

.row-click.is-blocked:hover[b-71d6s35wpz] {
    background: rgba(217, 119, 47, 0.18);
}

/* Boxed, because it is a STATE and not a thing the caller said. Everything else
   in this column is the customer's own words; a bare "Blocked number" in the
   same style would read as an intent they expressed. */
.blocked-tag[b-71d6s35wpz] {
    display: inline-block;
    padding: 2px 8px;
    border: 1px solid rgba(217, 119, 47, 0.55);
    border-radius: var(--radius-md, 6px);
    background: rgba(217, 119, 47, 0.12);
    color: #D9772F;
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
    cursor: default;
}

/* ---- Fitting the table without a sideways scroll ----

   The shared .table gives every cell 18px of padding on each side. Across eight
   columns that alone is nearly 300px of air, which is what pushed this table
   past the panel and made it scroll horizontally — the one thing a table must
   not do, because the columns that fall off the right are the ✉ and ✆ marks the
   owner came to read.

   Narrowed HERE rather than in app.css: every other table in the panel has
   fewer columns and reads better with the roomier default. */
.table th[b-71d6s35wpz], .table td[b-71d6s35wpz] {
    padding-left: 11px;
    padding-right: 11px;
}

/* "Caller wanted" is the only column with free text, so it is the one that
   stretches. Capped and ellipsised: the full text is in the drawer one click
   away, and a long intent must not be allowed to widen the whole table.

   A class rather than :nth-child — a positional selector keeps matching after a
   column is added or removed, and would then quietly clamp the wrong one. This
   table just lost its Language column, which is exactly how that happens. */
.td-wanted[b-71d6s35wpz] {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---- Text column ----
   Narrow and centred: it carries one glyph, and left-aligned single characters
   under a wider heading drift away from the column they belong to. */
.th-sms[b-71d6s35wpz], .td-sms[b-71d6s35wpz] {
    width: 46px;
    text-align: center;
    white-space: nowrap;
}

/* The ✉ for a caller who was texted. Given the brand saffron rather than left
   grey, because in a column of dashes the eye is looking for the exceptions —
   the opposite of the Dashboard, where the mark sits beside a number it must
   not compete with. */
.sms-yes[b-71d6s35wpz] {
    font-size: 12.5px;
    color: var(--saffron-soft, #E9A13B);
    cursor: default;
}

/* Its own class rather than reusing .th-sms: "Transfer" does not fit in 46px and
   would wrap to two lines in the header. */
.th-transfer[b-71d6s35wpz], .td-transfer[b-71d6s35wpz] {
    width: 68px;
    text-align: center;
    white-space: nowrap;
}

/* A DIFFERENT colour from the ✉, deliberately. The two columns sit side by side
   and mean unrelated things — one is a confirmation the salon sent, the other is
   the receptionist handing the caller to a person. In saffron they would read as
   two halves of one idea.

   --ok, not --lajvard: that token is aliased to a BACKGROUND in this theme
   (--glass-bg), so text painted with it is invisible, and --lajvard-soft does not
   exist at all — a var() fallback would have silently shipped the hard-coded
   colour past every theme. --ok is semantic and defined in all of them. Reaching
   a human is a good outcome, not a fault, so green also reads correctly. */
.transfer-yes[b-71d6s35wpz] {
    font-size: 12.5px;
    color: var(--ok);
    cursor: default;
}
/* /Components/Pages/Customers.razor.rz.scp.css */
/* The salon's address book. Same table language as the dashboard's
   appointments, because it is the same object seen from a different angle. */

.page-header[b-wlxl8t9kg5] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}

.page-title[b-wlxl8t9kg5] { font-size: 17px; font-weight: 700; }

.page-sub[b-wlxl8t9kg5] {
    font-size: 12px;
    color: var(--text-faint);
    margin-top: 3px;
}

/* Sits in the card header where the row count usually goes: with a few hundred
   customers, finding one IS the header's job. */
.search[b-wlxl8t9kg5] {
    width: 260px;
    max-width: 45vw;
    padding: 6px 10px;
    font-size: 12px;
}

.cust-name[b-wlxl8t9kg5] { vertical-align: middle; }

.cust-phone[b-wlxl8t9kg5] {
    display: block;
    margin-left: 34px;
    margin-top: 1px;
    font-size: 10.5px;
}

/* Blocked rows stay legible rather than greyed to nothing — the owner has to be
   able to read who they blocked in order to unblock them. The badge does the
   telling. */
.row-blocked .cust-name[b-wlxl8t9kg5] { color: var(--text-dim); }

.actions[b-wlxl8t9kg5] { display: flex; gap: 5px; justify-content: flex-end; }

/* ---------- Action pills ---------- */

/* Frosted glass, one colour per action, so the row reads at a glance instead of
   being three identical grey buttons the owner has to stop and read.

   The colours are literals rather than theme tokens on purpose: these are
   semantic (look / change / stop), and an accent-coloured "Block" would turn
   gold in the gold theme and stop meaning danger. */
.pill[b-wlxl8t9kg5] {
    padding: 4px 11px;
    border-radius: 999px;
    border: 1px solid;
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transition: background .15s, border-color .15s, transform .1s;
}

.pill:hover[b-wlxl8t9kg5] { transform: translateY(-1px); }
.pill:active[b-wlxl8t9kg5] { transform: translateY(0); }

/* Look — the safe one, and the quietest. */
.pill-view[b-wlxl8t9kg5] {
    color: #A5C8F0;
    background: rgba(120, 180, 255, 0.10);
    border-color: rgba(120, 180, 255, 0.30);
}
.pill-view:hover[b-wlxl8t9kg5] {
    background: rgba(120, 180, 255, 0.20);
    border-color: rgba(120, 180, 255, 0.55);
}

/* Change — amber, the "this writes something" colour used for money elsewhere. */
.pill-edit[b-wlxl8t9kg5] {
    color: #F2BE72;
    background: rgba(233, 161, 59, 0.10);
    border-color: rgba(233, 161, 59, 0.30);
}
.pill-edit:hover[b-wlxl8t9kg5] {
    background: rgba(233, 161, 59, 0.20);
    border-color: rgba(233, 161, 59, 0.55);
}

/* Stop — red, and only ever this. */
.pill-block[b-wlxl8t9kg5] {
    color: #E88A84;
    background: rgba(180, 55, 47, 0.12);
    border-color: rgba(248, 113, 113, 0.30);
}
.pill-block:hover[b-wlxl8t9kg5] {
    background: rgba(180, 55, 47, 0.24);
    border-color: rgba(248, 113, 113, 0.6);
}

/* Undo the stop — green, because it gives the customer back. */
.pill-unblock[b-wlxl8t9kg5] {
    color: #86EFAC;
    background: rgba(74, 222, 128, 0.10);
    border-color: rgba(74, 222, 128, 0.30);
}
.pill-unblock:hover[b-wlxl8t9kg5] {
    background: rgba(74, 222, 128, 0.20);
    border-color: rgba(74, 222, 128, 0.55);
}

/* ---------- Read-only card ---------- */

.view-head[b-wlxl8t9kg5] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--glass-border);
}

.av-lg[b-wlxl8t9kg5] {
    width: 42px;
    height: 42px;
    margin-right: 0;
    font-size: 14px;
    flex: none;
}

.view-name[b-wlxl8t9kg5] { font-size: 15px; font-weight: 700; }
.view-phone[b-wlxl8t9kg5] { font-size: 12px; margin-top: 2px; }
.view-head .badge[b-wlxl8t9kg5] { margin-left: auto; }

/* ---------- The three numbers ---------- */

/* Who this person is to the salon, before any detail: how often, how much, how
   recently. Each tile owns a colour so the eye can tell them apart at a glance
   rather than reading three identical boxes. */
.stats[b-wlxl8t9kg5] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-top: 16px;
}

.stat[b-wlxl8t9kg5] {
    padding: 11px 8px;
    border-radius: var(--radius-md);
    border: 1px solid;
    text-align: center;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.stat-val[b-wlxl8t9kg5] { font-size: 18px; font-weight: 700; line-height: 1.2; }

.stat-lbl[b-wlxl8t9kg5] {
    font-size: 9.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .5px;
    color: var(--text-faint);
    margin-top: 3px;
}

/* Literals, not theme tokens: these are semantic (count / money / recency) and
   must keep meaning the same in all three themes. */
.stat-blue[b-wlxl8t9kg5] {
    background: rgba(120, 180, 255, 0.10);
    border-color: rgba(120, 180, 255, 0.28);
}
.stat-blue .stat-val[b-wlxl8t9kg5] { color: #A5C8F0; }

.stat-gold[b-wlxl8t9kg5] {
    background: rgba(233, 161, 59, 0.10);
    border-color: rgba(233, 161, 59, 0.28);
}
.stat-gold .stat-val[b-wlxl8t9kg5] { color: #F2BE72; }

.stat-green[b-wlxl8t9kg5] {
    background: rgba(74, 222, 128, 0.09);
    border-color: rgba(74, 222, 128, 0.26);
}
.stat-green .stat-val[b-wlxl8t9kg5] { color: #86EFAC; font-size: 14px; padding-top: 3px; }

/* ---------- Section headings ---------- */

.sec-lbl[b-wlxl8t9kg5] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 18px 0 9px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .8px;
    color: var(--text-faint);
}

/* A rule that fills whatever the label doesn't — divides without a heavy line. */
.sec-lbl[b-wlxl8t9kg5]::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--glass-border);
}

.tiny[b-wlxl8t9kg5] { font-size: 11.5px; }

/* ---------- Services taken ---------- */

.svc-list[b-wlxl8t9kg5] { display: flex; flex-direction: column; gap: 5px; }

/* Each row is its own little bar chart: the fill shows what they actually come
   for, scaled to their own most-booked service. */
.svc[b-wlxl8t9kg5] {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    overflow: hidden;
}

.svc-bar[b-wlxl8t9kg5] {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    background: linear-gradient(90deg, rgba(120, 180, 255, 0.20), rgba(120, 180, 255, 0.05));
    pointer-events: none;
}

.svc-name[b-wlxl8t9kg5] {
    position: relative;
    flex: 1;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-main);
}

.svc-times[b-wlxl8t9kg5] {
    position: relative;
    font-size: 12px;
    font-weight: 700;
    color: #A5C8F0;
}

.svc-total[b-wlxl8t9kg5] {
    position: relative;
    min-width: 3.2rem;
    text-align: right;
    font-size: 12px;
    font-weight: 700;
    color: #F2BE72;
}

/* ---------- Details ---------- */

/* A definition list, not a form: there is nothing here to type into, which is
   the point of the View action. */
.facts[b-wlxl8t9kg5] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px 16px;
    margin: 0;
}

.fact dt[b-wlxl8t9kg5] {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: .5px;
    margin-bottom: 3px;
}

.fact dd[b-wlxl8t9kg5] {
    margin: 0;
    font-size: 12.5px;
    color: var(--text-main);
}

/* ---------- Notes ---------- */

/* Amber and pinned near the top: an allergy is the most important thing on this
   card. It is always rendered, even empty — a section that disappears when
   there is nothing to say teaches the owner to stop looking for it. */
.view-notes[b-wlxl8t9kg5] {
    margin-top: 14px;
    padding: 11px 12px;
    border-radius: var(--radius-md);
    background: rgba(233, 161, 59, 0.09);
    border: 1px solid rgba(233, 161, 59, 0.28);
}

.notes-label[b-wlxl8t9kg5] {
    font-size: 10px;
    font-weight: 700;
    color: #F2BE72;
    text-transform: uppercase;
    letter-spacing: .5px;
    margin-bottom: 5px;
}

.view-notes p[b-wlxl8t9kg5] { font-size: 12.5px; line-height: 1.7; color: var(--text-dim); }

/* Nothing written yet: keep the frame, drop the shout. */
.notes-empty[b-wlxl8t9kg5] {
    background: var(--glass-bg-soft);
    border-color: var(--glass-border);
    border-style: dashed;
}

.notes-empty .notes-label[b-wlxl8t9kg5] { color: var(--text-faint); }

.view-blocked[b-wlxl8t9kg5] {
    margin-top: 12px;
    padding: 9px 12px;
    border-radius: var(--radius-md);
    background: rgba(180, 55, 47, 0.12);
    border: 1px solid rgba(248, 113, 113, 0.3);
    font-size: 12px;
    color: #E88A84;
}

.pair[b-wlxl8t9kg5] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.hint[b-wlxl8t9kg5] { font-size: 10.5px; }

textarea.area[b-wlxl8t9kg5] { resize: vertical; min-height: 66px; line-height: 1.6; }

.confirm[b-wlxl8t9kg5] { font-size: 12.5px; line-height: 1.7; color: var(--text-dim); }
.confirm strong[b-wlxl8t9kg5] { color: var(--text-main); }
.confirm + .confirm[b-wlxl8t9kg5] { margin-top: 8px; }
.confirm + .confirm + .field[b-wlxl8t9kg5] { margin-top: 14px; }

@media (max-width: 700px) {
    .pair[b-wlxl8t9kg5] { grid-template-columns: 1fr; }
    .facts[b-wlxl8t9kg5] { grid-template-columns: 1fr; }
    .search[b-wlxl8t9kg5] { width: 100%; }
}
/* /Components/Pages/Dashboard.razor.rz.scp.css */
/* Dashboard — layout from the supplied template, colours from the brand. */

.page-header[b-m3rk0xm92z] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

.page-title[b-m3rk0xm92z] { font-size: 17px; font-weight: 700; }
.page-sub[b-m3rk0xm92z] { font-size: 12px; color: var(--ink-dim); margin-top: 2px; }

.header-actions[b-m3rk0xm92z] { display: flex; align-items: center; gap: 6px; }

.date-pick[b-m3rk0xm92z] {
    width: auto;
    /* The native picker indicator is black-on-black without this. */
    color-scheme: dark;
    padding: 6px 10px;
    font-size: 12px;
}

/* ---------- Stat cards ---------- */

/* Six across, and they must STAY six across on a normal laptop.
   The trap: a viewport media query is the wrong ruler here. The sidebar is
   232px and .content adds 22px of padding each side, so this grid gets roughly
   276px LESS than the window — a `max-width: 1450px` breakpoint was really
   asking about a ~1174px box, and a 1440px laptop fell to three rows.
   Columns are sized from the grid's own width instead, so the layout responds
   to the space it actually has. */
.stats-grid[b-m3rk0xm92z] {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 8px;
    margin-bottom: 18px;
}

/* Same glass as the login card — the tint rides on top of it, so the tiles
   read as panes over the backdrop rather than flat coloured rectangles. */
.stat-card[b-m3rk0xm92z] {
    border-radius: var(--r);
    /* Tightened when the sixth tile arrived — six at the old padding pushed the
       labels to two lines and the day's schedule below the fold. */
    padding: 12px 12px;
    /* Without this a long meta line ("120 minutes talked") sets the column's
       minimum width and quietly forces the whole row to wrap. */
    min-width: 0;
    border: 1px solid;
    position: relative;
    overflow: hidden;
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    transition: transform 0.2s, box-shadow 0.2s;
    cursor: default;
}

/* The lit top edge, as on every other surface. */
.stat-card[b-m3rk0xm92z]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-edge-lit) 45%, transparent);
    pointer-events: none;
    z-index: 1;
}

.stat-card:hover[b-m3rk0xm92z] { transform: translateY(-2px); }

/* The corner bloom that gives each tile its tint. */
.stat-card[b-m3rk0xm92z]::after {
    content: "";
    position: absolute;
    top: -20px;
    right: -20px;
    width: 70px;
    height: 70px;
    border-radius: 50%;
    filter: blur(20px);
}

/* Each tint is layered over the same navy glass base, never over black. */
.stat-blue[b-m3rk0xm92z] {
    background: linear-gradient(160deg, rgba(78, 134, 224, 0.16), rgba(24, 38, 66, 0.62));
    border-color: rgba(78, 134, 224, 0.28);
    box-shadow: var(--shadow), 0 0 22px rgba(78, 134, 224, 0.1);
}
.stat-blue[b-m3rk0xm92z]::after { background: rgba(78, 134, 224, 0.2); }

.stat-green[b-m3rk0xm92z] {
    background: linear-gradient(160deg, rgba(74, 222, 128, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(74, 222, 128, 0.26);
    box-shadow: var(--shadow), 0 0 22px rgba(74, 222, 128, 0.08);
}
.stat-green[b-m3rk0xm92z]::after { background: rgba(74, 222, 128, 0.18); }

.stat-purple[b-m3rk0xm92z] {
    background: linear-gradient(160deg, rgba(167, 139, 250, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(167, 139, 250, 0.26);
    box-shadow: var(--shadow), 0 0 22px rgba(167, 139, 250, 0.08);
}
.stat-purple[b-m3rk0xm92z]::after { background: rgba(167, 139, 250, 0.18); }

/* Texting. Its own hue rather than reusing one — six tiles in a row need six
   distinguishable colours, or the eye stops using colour to navigate at all. */
.stat-pink[b-m3rk0xm92z] {
    background: linear-gradient(160deg, rgba(244, 114, 182, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(244, 114, 182, 0.26);
    box-shadow: var(--shadow), 0 0 22px rgba(244, 114, 182, 0.08);
}

.stat-pink[b-m3rk0xm92z]::after { background: rgba(244, 114, 182, 0.18); }

/* The ✉ beside a caller who was texted. Quiet on purpose: it confirms something
   that already went well, so it must not compete with the number itself. */
.sms-mark[b-m3rk0xm92z] {
    margin-left: 6px;
    font-size: 11px;
    opacity: 0.55;
    cursor: default;
}

/* Money wears the brand's saffron — the one tile an owner looks for first. */
.stat-amber[b-m3rk0xm92z] {
    background: linear-gradient(160deg, rgba(233, 161, 59, 0.17), rgba(24, 38, 66, 0.62));
    border-color: rgba(233, 161, 59, 0.32);
    box-shadow: var(--shadow), 0 0 22px rgba(233, 161, 59, 0.12);
}
.stat-amber[b-m3rk0xm92z]::after { background: rgba(233, 161, 59, 0.22); }

.stat-cyan[b-m3rk0xm92z] {
    background: linear-gradient(160deg, rgba(34, 211, 238, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(34, 211, 238, 0.26);
    box-shadow: var(--shadow), 0 0 22px rgba(34, 211, 238, 0.08);
}
.stat-cyan[b-m3rk0xm92z]::after { background: rgba(34, 211, 238, 0.18); }

/* Transfer to a person. A seventh hue, distinct from the six above for the same
   reason they are distinct from each other. */
.stat-indigo[b-m3rk0xm92z] {
    background: linear-gradient(160deg, rgba(129, 140, 248, 0.13), rgba(24, 38, 66, 0.62));
    border-color: rgba(129, 140, 248, 0.26);
    box-shadow: var(--shadow), 0 0 22px rgba(129, 140, 248, 0.08);
}
.stat-indigo[b-m3rk0xm92z]::after { background: rgba(129, 140, 248, 0.18); }

/* "needs a number and hours" — the transfer is switched ON but cannot happen.
   Amber rather than red: nothing is broken and no money is at risk, but the
   owner believes something works that does not, so it must not read as ordinary
   dim text either. Explicit rgba, not a --danger token: that token does not
   exist in this theme and would silently fall through to inherited colour. */
.warn[b-m3rk0xm92z] {
    color: rgba(233, 161, 59, 0.95);
}

.stat-icon-top[b-m3rk0xm92z] {
    position: absolute;
    top: 12px;
    right: 14px;
    font-size: 15px;
    opacity: 0.4;
}

.stat-val[b-m3rk0xm92z] {
    font-size: 19px;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.02em;
    color: var(--ink);
    /* Room for the corner icon, so a five-figure number never runs under it. */
    padding-right: 18px;
}

.stat-unit[b-m3rk0xm92z] { font-size: 12px; font-weight: 600; color: var(--ink-dim); }

/* The label and meta lines are what decide whether six tiles fit. Both are
   clipped rather than wrapped: a tile that grows a second line pushes the whole
   grid taller and the day's schedule below the fold, whereas a truncated label
   still reads (the number above it carries the meaning) and the full text stays
   available on hover via the title attribute. */
.stat-lbl[b-m3rk0xm92z] {
    font-size: 11px;
    font-weight: 600;
    color: var(--ink-muted);
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.stat-meta[b-m3rk0xm92z] {
    font-size: 10.5px;
    color: var(--ink-faint);
    margin-top: 5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Usage against the plan cap, in the tile's own meta line. */
.under[b-m3rk0xm92z] { color: var(--ok); font-weight: 700; }
.near[b-m3rk0xm92z] { color: var(--warn); font-weight: 700; }
.over[b-m3rk0xm92z] { color: var(--crit); font-weight: 700; }

/* ---------- Two column ---------- */

.two-col[b-m3rk0xm92z] {
    display: grid;
    grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr);
    gap: 14px;
    align-items: start;
}

.right-col[b-m3rk0xm92z] {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* ---------- Appointments table ---------- */

.time-cell[b-m3rk0xm92z] { font-weight: 700; color: var(--accent2) !important; }
.price[b-m3rk0xm92z] { color: var(--saffron-soft) !important; font-weight: 700; }

.cust-name[b-m3rk0xm92z] { vertical-align: middle; }

.cust-phone[b-m3rk0xm92z] {
    display: block;
    margin-left: 34px;
    margin-top: 1px;
    font-size: 10.5px;
}

/* A cancelled row stays visible but stops competing — the history remains,
   the eye skips it. */
.row-cancelled td[b-m3rk0xm92z] { opacity: 0.45; }
.row-cancelled .cust-name[b-m3rk0xm92z] { text-decoration: line-through; }

/* ---------- Call list ---------- */

.sch-list[b-m3rk0xm92z] { display: flex; flex-direction: column; gap: 9px; }

.sch-item[b-m3rk0xm92z] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.sch-time[b-m3rk0xm92z] {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--accent2);
    width: 38px;
    flex-shrink: 0;
}

.sch-bar[b-m3rk0xm92z] {
    width: 3px;
    align-self: stretch;
    min-height: 30px;
    border-radius: 3px;
    background: linear-gradient(to bottom, var(--accent), var(--accent2));
    flex-shrink: 0;
}

.sch-text[b-m3rk0xm92z] { min-width: 0; flex: 1; }

.sch-name[b-m3rk0xm92z] {
    font-size: 12px;
    font-weight: 600;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sch-room[b-m3rk0xm92z] { font-size: 10.5px; color: var(--ink-faint); margin-top: 1px; }

.sch-cnt[b-m3rk0xm92z] {
    font-size: 11px;
    color: var(--ink-dim);
    flex-shrink: 0;
}

/* ---------- Week chart ---------- */

.chart-wrap[b-m3rk0xm92z] { display: flex; flex-direction: column; gap: 6px; }

.bars[b-m3rk0xm92z] {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 6px;
    height: 88px;
}

.bar[b-m3rk0xm92z] {
    flex: 1;
    border-radius: 4px 4px 0 0;
    background: linear-gradient(to top, rgba(78, 134, 224, 0.75), rgba(124, 202, 255, 0.5));
    transition: filter 0.15s;
    min-height: 3px;
}

.bar:hover[b-m3rk0xm92z] { filter: brightness(1.3); }

/* Today is saffron — the bar the owner is standing in. */
.bar-today[b-m3rk0xm92z] {
    background: linear-gradient(to top, var(--saffron), var(--saffron-soft));
    box-shadow: 0 0 12px rgba(233, 161, 59, 0.35);
}

.bar-labels[b-m3rk0xm92z] {
    display: flex;
    justify-content: space-between;
    gap: 6px;
}

.bar-lbl[b-m3rk0xm92z] {
    flex: 1;
    text-align: center;
    font-size: 9.5px;
    color: var(--ink-faint);
}

.lbl-today[b-m3rk0xm92z] { color: var(--saffron); font-weight: 700; }

/* ---------- Responsive ---------- */

/* Below a genuinely narrow window six become unreadable, so fall to three then
   two. These thresholds are deliberately far lower than the old 1450px: with
   the tightened padding and type above, six tiles fit comfortably in the
   ~1160px box a 1440px laptop actually gives this grid. */
@media (max-width: 1180px) {
    .stats-grid[b-m3rk0xm92z] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 1100px) {
    .two-col[b-m3rk0xm92z] { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
    .stats-grid[b-m3rk0xm92z] { grid-template-columns: repeat(2, 1fr); }
}

/* Separates the usage figure from the days remaining. Dimmed so the minutes stay
   the thing the eye lands on — the reset date is context, not the headline. */
.stat-sep[b-m3rk0xm92z] {
    opacity: .45;
    margin: 0 2px;
}
/* /Components/Pages/ForgotPassword.razor.rz.scp.css */
/* Password-reset pages.
 *
 * These rules are DUPLICATED from Login.razor.css rather than shared, because
 * Blazor's scoped CSS does not cross components: markup copied from the login
 * page renders completely unstyled here. Only the parts these pages actually use
 * are copied — the card, the form panel, the inputs and the button — not the
 * slideshow half.
 *
 * ResetPassword.razor.css is deliberately identical. Two small copies beat a
 * shared global stylesheet that any page could then depend on by accident.
 */

.login-page[b-9ca4la43qi] {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
    background: var(--bg-gradient);
}

.card[b-9ca4la43qi] {
    width: min(940px, 100%);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border: 1px solid var(--glass-border);
    box-shadow: 0 26px 70px rgba(0, 0, 0, 0.55), 0 0 25px var(--accent-glow-soft);
    border-radius: var(--radius-xl);
    overflow: hidden;
    position: relative;
    z-index: 2;
}

/* One column, unlike the login card's two: there is no slideshow here, and a
   half-empty 940px card reads as a broken page. */
.card.auth-narrow[b-9ca4la43qi] {
    width: min(440px, 100%);
}

.left[b-9ca4la43qi] {
    padding: 40px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.logo-row[b-9ca4la43qi] {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
}

.logo-icon[b-9ca4la43qi] {
    width: 34px;
    height: 34px;
    border-radius: 9px;
    background: var(--accent-glow-soft);
    border: 1px solid var(--glass-border);
    flex: none;
}

.logo-text-title[b-9ca4la43qi] {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.2;
}

.logo-text-sub[b-9ca4la43qi] {
    font-size: 11px;
    color: var(--text-dim);
}

.left h1[b-9ca4la43qi] {
    font-size: 22px;
    font-weight: 700;
    color: var(--text);
    margin: 4px 0 0;
}

.auth-note[b-9ca4la43qi] {
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-dim);
    margin: 0;
}

.auth-note strong[b-9ca4la43qi] {
    color: var(--text);
    font-weight: 600;
    /* A long address must not push the card wider than the viewport. */
    word-break: break-word;
}

.form[b-9ca4la43qi] {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 6px;
}

.left input[b-9ca4la43qi] {
    width: 100%;
    padding: 11px 13px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
}

.left input[b-9ca4la43qi]::placeholder { color: var(--text-faint); }

.left input:focus[b-9ca4la43qi] {
    outline: none;
    border-color: var(--text-dim);
}

.left button[b-9ca4la43qi] {
    width: 100%;
    padding: 11px 16px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: transform .12s ease, border-color .12s ease;
}

.left button:hover:not(:disabled)[b-9ca4la43qi] {
    transform: translateY(-1px);
    border-color: var(--text-dim);
}

.left button:active:not(:disabled)[b-9ca4la43qi] { transform: translateY(0); }

.left button:disabled[b-9ca4la43qi] {
    opacity: .45;
    cursor: default;
}

.alert-box[b-9ca4la43qi] {
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius-md);
    font-size: 13px;
    color: var(--text-error);
    background: rgba(180, 55, 47, 0.16);
    border: 1px solid rgba(217, 86, 76, 0.4);
}

/* A link that looks like a link but is a button — it changes state on this page
   rather than navigating, and a real <a href="#"> would jump the scroll. */
.linkish[b-9ca4la43qi] {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--text);
    text-decoration: underline;
    cursor: pointer;
    width: auto !important;
}

.auth-back[b-9ca4la43qi] {
    margin-top: 6px;
    font-size: 12px;
    color: var(--text-dim);
    text-decoration: none;
}

.auth-back:hover[b-9ca4la43qi] { text-decoration: underline; }

.btn-primary-link[b-9ca4la43qi] {
    display: block;
    text-align: center;
    padding: 11px 16px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    margin-top: 6px;
}

.btn-primary-link:hover[b-9ca4la43qi] { border-color: var(--text-dim); }

.sr-only[b-9ca4la43qi] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* /Components/Pages/Login.razor.rz.scp.css */
/* ============================================================
   Login.razor.css — scoped by Blazor's CSS isolation, so nothing
   here leaks out and nothing outside reaches in.

   Structure follows the supplied template (two-panel card, glass,
   orbs, scan line, slider). The variables it referenced
   (--accent-gradient, --glass-bg, --orb-1 …) belong to another
   product, so they are defined here in Avacallix's own brand:
   lajvard #23509B, saffron #E9A13B, pomegranate #B4372F.

   The whole page is wrapped in .login-page — body is outside this
   component, so isolation cannot reach it; a fixed ::before on the
   wrapper still covers the viewport.
   ============================================================ */

/* Every token here comes from theme.css — nothing is redefined locally, so this
   page follows blue/gold/lilac like the rest of the panel. */
.login-page[b-nb5ndjldlm] {
    min-height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 1.5rem;
    color: var(--ink);
    position: relative;
    overflow: hidden;
}

/* Grid + glow orbs */
.login-page[b-nb5ndjldlm]::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(circle 460px at 88% 8%, var(--orb-1), transparent 70%),
        radial-gradient(circle 520px at 4% 96%, var(--orb-2), transparent 70%),
        radial-gradient(circle 260px at 60% 85%, var(--orb-3), transparent 70%),
        linear-gradient(var(--grid-line) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
    background-size:
        auto, auto, auto,
        var(--grid-size) var(--grid-size),
        var(--grid-size) var(--grid-size);
    -webkit-mask-image: radial-gradient(ellipse 75% 75% at 50% 45%, rgba(0,0,0,0.9), transparent 80%);
    mask-image: radial-gradient(ellipse 75% 75% at 50% 45%, rgba(0,0,0,0.9), transparent 80%);
    animation: login-orb-drift-b-nb5ndjldlm 24s ease-in-out infinite alternate;
}

@keyframes login-orb-drift-b-nb5ndjldlm {
    from { background-position: 0 0, 0 0, 0 0, 0 0, 0 0; }
    to   { background-position: -30px 30px, 40px -30px, -20px 20px, 0 0, 0 0; }
}

/* Scan line */
.login-page[b-nb5ndjldlm]::after {
    content: "";
    position: fixed;
    left: 0;
    right: 0;
    top: -2px;
    height: 2px;
    z-index: 1;
    pointer-events: none;
    opacity: 0.5;
    background: linear-gradient(90deg, transparent, var(--scanline) 50%, transparent);
    animation: login-scan-sweep-b-nb5ndjldlm 7s linear infinite;
}

@keyframes login-scan-sweep-b-nb5ndjldlm {
    0%   { top: -2px; }
    100% { top: 100%; }
}

/* ---------- Main card ---------- */

.card[b-nb5ndjldlm] {
    width: min(940px, 100%);
    height: 540px;
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border: 1px solid var(--glass-border);
    box-shadow: 0 26px 70px rgba(0, 0, 0, 0.55), 0 0 25px var(--accent-glow-soft);
    border-radius: var(--radius-xl);
    /* Form left, slideshow right — the wider column carries the imagery. */
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    overflow: hidden;
    position: relative;
    z-index: 2;
}

/* ---------- Form panel ---------- */

.left[b-nb5ndjldlm] {
    padding: 40px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 14px;
    min-width: 0;
}

.logo-row[b-nb5ndjldlm] {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

/* The logo mark image. No background or gradient behind it: the artwork
 * carries its own gold and a transparent surround, so a themed square would
 * show as a coloured rectangle poking out from under the glyph. The glow is
 * kept and stays themed, so the mark belongs to each palette.
 *
 * Larger than the sidebar's copy on purpose: this is the first screen anyone
 * sees and there is no surrounding chrome competing with it. */
.logo-icon[b-nb5ndjldlm] {
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    object-fit: contain;
    filter: drop-shadow(0 0 9px var(--accent-glow));
}

.logo-text-title[b-nb5ndjldlm] {
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
}

.logo-text-sub[b-nb5ndjldlm] {
    font-size: 11px;
    color: var(--ink-dim);
}

.left h1[b-nb5ndjldlm] {
    font-size: 26px;
    margin-bottom: 4px;
}

.form[b-nb5ndjldlm] {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.input[b-nb5ndjldlm] {
    margin-bottom: 18px;
}

.left input[b-nb5ndjldlm] {
    width: 100%;
    padding: 12px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--sunken);
    color: var(--ink);
    font-family: inherit;
    font-size: 15px;
    outline: none;
    transition: border-color 0.2s, box-shadow 0.2s;
}

.left input[b-nb5ndjldlm]::placeholder {
    color: var(--ink-dim);
}

.left input:focus[b-nb5ndjldlm] {
    border-color: #7CCAFF;
    box-shadow: 0 0 12px var(--accent-glow-soft);
}

.left button[b-nb5ndjldlm] {
    width: 100%;
    padding: 12px;
    border-radius: var(--radius-md);
    border: none;
    background: var(--accent-gradient);
    color: var(--accent-text-on-fill);
    font-family: inherit;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 0 18px var(--accent-glow);
    transition: transform 0.2s, box-shadow 0.2s;
}

.left button:hover[b-nb5ndjldlm] {
    transform: translateY(-2px);
    box-shadow: 0 0 25px var(--accent-glow);
}

.left button:active[b-nb5ndjldlm] { transform: translateY(0); }

.alert-box[b-nb5ndjldlm] {
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius-md);
    font-size: 13px;
    color: var(--text-error);
    background: rgba(180, 55, 47, 0.16);
    border: 1px solid rgba(217, 86, 76, 0.4);
}

.forgot[b-nb5ndjldlm] {
    margin-top: 2px;
    font-size: 12px;
    color: var(--ink-dim);
    cursor: pointer;
    text-align: right;
}

.forgot:hover[b-nb5ndjldlm] { text-decoration: underline; }

/* The way in for somebody who has no account yet. Separated from the form by a
   rule rather than sitting under it, so it does not read as another thing to
   fill in before signing in. */
.signup-prompt[b-nb5ndjldlm] {
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--glass-border);
    font-size: 12.5px;
    color: var(--text-faint);
    text-align: center;
}

.signup-prompt a[b-nb5ndjldlm] { color: var(--text-dim); text-decoration: underline; }
.signup-prompt a:hover[b-nb5ndjldlm] { color: var(--text-main); }

/* Labels exist for screen readers; the placeholder carries the visual. */
.sr-only[b-nb5ndjldlm] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Shake, triggered from Login.razor.js on a failed sign-in. */
.shake[b-nb5ndjldlm] { animation: login-shake-b-nb5ndjldlm 0.35s ease-in-out; }

@keyframes login-shake-b-nb5ndjldlm {
    10%, 90% { transform: translateX(-2px); }
    20%, 80% { transform: translateX(4px); }
    30%, 50%, 70% { transform: translateX(-8px); }
    40%, 60% { transform: translateX(8px); }
}

/* ---------- Slider panel ---------- */

.right[b-nb5ndjldlm] {
    position: relative;
    overflow: hidden;
    /* Navy, not black — it shows through while a slide image loads. */
    background: linear-gradient(160deg, #12233F, #0A1122);
}

.right img[b-nb5ndjldlm] {
    width: 100%;
    height: 100%;
    /* CONTAIN, not cover. These are composed marketing images with a title and a
       dashboard in them, not backdrop photography: cover fills the panel and
       crops whatever does not fit, and since the artwork is wide (≈16:9) against
       a tall panel, that cut the sides off every slide — the product name on one
       of them included. A letterboxed image that reads is worth more than a
       full-bleed one that is missing half its subject.

       The gap contain leaves is filled by .right's own gradient, which is why
       that background exists rather than being black. */
    object-fit: contain;
    /* Slightly above centre: the scrim and caption occupy the bottom third, so
       centring exactly would push the subject behind the text. */
    object-position: center 42%;
    padding: 18px;
    /* Explicit: this stylesheet has no global reset, so without it the padding
       is ADDED to the 100% width/height and the image overflows the panel it
       was just made to fit inside. */
    box-sizing: border-box;
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 1s ease-in-out;
}

.right img.show[b-nb5ndjldlm] { opacity: 1; }

/* A scrim under the caption: an ad image is arbitrary, and white text on a
   bright photo is unreadable without it. */
.right[b-nb5ndjldlm]::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to top, rgba(7, 12, 22, 0.85) 0%, transparent 55%);
}

.slide-text[b-nb5ndjldlm] {
    position: absolute;
    right: 36px;
    left: 36px;
    bottom: 44px;
    z-index: 2;
    background: var(--glass-bg-soft);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
    background-clip: padding-box;
    padding: 18px 22px;
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 1s ease, transform 1s ease;
    pointer-events: none;
    box-shadow:
        0 18px 40px rgba(0, 0, 0, 0.85),
        0 0 22px var(--accent-glow-soft),
        inset 0 0 12px var(--accent-glow-soft);
}

/* Gradient hairline border via mask-composite. */
.slide-text[b-nb5ndjldlm]::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--radius-lg);
    padding: 1px;
    background: var(--accent-gradient);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    pointer-events: none;
}

.slide-text.show[b-nb5ndjldlm] {
    opacity: 1;
    transform: translateY(0);
    /* Only the visible caption is clickable — the stacked hidden ones must not
       swallow clicks meant for the link underneath. */
    pointer-events: auto;
}

.slide-text h2[b-nb5ndjldlm] {
    font-size: 20px;
    margin-bottom: 6px;
    color: var(--ink);
}

.slide-text p[b-nb5ndjldlm] {
    margin: 0;
    font-size: 13.5px;
    color: var(--ink-muted);
    line-height: 1.75;
}

.slide-link[b-nb5ndjldlm] {
    display: inline-block;
    margin-top: 10px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--saffron-soft);
}

/* ---------- Dots ---------- */

.dots[b-nb5ndjldlm] {
    position: absolute;
    bottom: 16px;
    left: 36px;
    z-index: 3;
    display: flex;
    gap: 6px;
}

.dot[b-nb5ndjldlm] {
    width: 7px;
    height: 7px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.3);
    cursor: pointer;
    transition: background 0.25s, width 0.25s;
}

.dot.on[b-nb5ndjldlm] {
    width: 18px;
    border-radius: 4px;
    background: var(--saffron);
}

.footer[b-nb5ndjldlm] {
    position: absolute;
    bottom: 12px;
    right: 20px;
    z-index: 3;
    font-size: 11px;
    color: rgba(238, 243, 252, 0.45);
}

/* ---------- Responsive ---------- */

@media (max-width: 820px) {
    /* The slider is decoration; on a phone the form is the whole job. */
    .card[b-nb5ndjldlm] {
        grid-template-columns: 1fr;
        height: auto;
        max-width: 420px;
    }

    .right[b-nb5ndjldlm] { display: none; }
    .left[b-nb5ndjldlm] { padding: 32px 26px; }
}

@media (prefers-reduced-motion: reduce) {
    .login-page[b-nb5ndjldlm]::before,
    .login-page[b-nb5ndjldlm]::after,
    .shake[b-nb5ndjldlm] {
        animation: none;
    }

    .right img[b-nb5ndjldlm],
    .slide-text[b-nb5ndjldlm] {
        transition: none;
    }
}
/* /Components/Pages/NewBooking.razor.rz.scp.css */
/* Manual booking — the public page's week grid, inside the panel.
 *
 * These rules are copied from PublicSite.razor.css rather than shared: Blazor's
 * scoped CSS does not cross components, so the same markup renders completely
 * unstyled here. Only the calendar parts are copied, not the microsite's hero,
 * gallery or footer.
 *
 * Every colour is a theme token. The panel runs three themes and a literal hex
 * looks right in one and wrong in the other two.
 */

/* ---------- What & who ---------- */

/* Service and staff on ONE row, side by side: "a colour, with Maryam" is a
   single thought and must not wrap into two. Equal columns rather than
   auto-width, so the two selects line up instead of jostling as their contents
   change length. */
.pick-row[b-wf7y9hdcdc] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    align-items: end;
}

.pick-field[b-wf7y9hdcdc] { min-width: 0; }

.pick-field .label[b-wf7y9hdcdc] {
    display: block;
    margin-bottom: 6px;
}

/* A tinted top edge so the card reads as the page's first step rather than a
   grey strip. Layered OVER --glass-bg-soft, never replacing it, or the glass
   goes flat. */
.pick-card[b-wf7y9hdcdc] {
    position: relative;
    overflow: hidden;
    background:
        linear-gradient(180deg,
            color-mix(in srgb, var(--svc-lajvard) 10%, transparent),
            transparent 70%),
        var(--glass-bg);
}

.pick-card[b-wf7y9hdcdc]::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 2px;
    background: linear-gradient(90deg,
        var(--svc-lajvard), var(--svc-turquoise), var(--svc-plum));
    opacity: .8;
}

/* Only the phone gets a stacked layout — above that the row is the point. */
@media (max-width: 560px) {
    .pick-row[b-wf7y9hdcdc] { grid-template-columns: 1fr; }
}

/* The calendar card carries the same tinted edge in the accent that marks a
   free hour, so the two cards read as one flow: choose, then pick. */
.cal-card[b-wf7y9hdcdc] {
    position: relative;
    overflow: hidden;
}

.cal-card[b-wf7y9hdcdc]::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 2px;
    background: linear-gradient(90deg,
        var(--svc-pistachio), var(--svc-turquoise));
    opacity: .7;
}

.cal-card .card-title[b-wf7y9hdcdc] {
    font-variant-numeric: tabular-nums;
    letter-spacing: .01em;
}

/* ---------- Week grid ---------- */

.week-grid[b-wf7y9hdcdc] {
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    backdrop-filter: blur(14px) saturate(130%);
    -webkit-backdrop-filter: blur(14px) saturate(130%);
    /* Lifted off the card behind it: the grid is the object on this page, and a
       flat panel on a flat card is what made it read as lifeless. */
    box-shadow: 0 10px 30px rgb(0 0 0 / .28), inset 0 1px 0 rgb(255 255 255 / .05);
}

/* The 54px first column is the time gutter; the seven that follow are the days.
   Head and body MUST use the same template or the columns drift apart. */
.week-head[b-wf7y9hdcdc] {
    display: grid;
    grid-template-columns: 54px repeat(7, minmax(0, 1fr));
    border-bottom: 1px solid var(--glass-border);
    /* The header is its own pane of glass, a shade denser than the body, so the
       days read as headings rather than as the first row of cells. */
    background: linear-gradient(180deg,
        rgb(255 255 255 / .06), transparent);
}

.week-head-cell[b-wf7y9hdcdc] {
    padding: 9px 4px;
    text-align: center;
    border-left: 1px solid var(--glass-border);
}

/* Today is marked with a coloured underline, not just a wash: on a busy grid a
   faint background tint disappears among the hover states. */
.week-head-cell.is-today[b-wf7y9hdcdc] {
    background: color-mix(in srgb, var(--svc-turquoise) 14%, transparent);
    box-shadow: inset 0 -2px 0 var(--svc-turquoise);
}

.week-head-cell.is-today .wh-date[b-wf7y9hdcdc] { color: var(--svc-turquoise-lit); }

.wh-day[b-wf7y9hdcdc] {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-faint);
}

.wh-date[b-wf7y9hdcdc] {
    font-size: 16px;
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.week-body[b-wf7y9hdcdc] {
    display: grid;
    grid-template-columns: 54px repeat(7, minmax(0, 1fr));
    max-height: 560px;
    overflow-y: auto;
}

.time-col[b-wf7y9hdcdc] { display: flex; flex-direction: column; }

.time-slot[b-wf7y9hdcdc] {
    height: 52px;
    padding: 2px 5px 0 0;
    border-top: 1px solid var(--glass-border);
    font-size: 10px;
    color: var(--text-faint);
    text-align: right;
    /* Pulled up so the label sits ON the line it names rather than under it. */
    transform: translateY(-7px);
}

.day-col[b-wf7y9hdcdc] {
    border-left: 1px solid var(--glass-border);
    min-width: 0;
}

/* Very faint: today's column has to be findable without competing with the
   green that marks every bookable hour inside it. */
.day-col.is-today[b-wf7y9hdcdc] {
    background: color-mix(in srgb, var(--svc-turquoise) 6%, transparent);
}

/* Past days are hatched rather than hidden: the week still has to read as a
   week, with the gone days visibly gone. */
.day-col.is-past[b-wf7y9hdcdc] {
    background: repeating-linear-gradient(45deg,
        rgba(255, 255, 255, .012), rgba(255, 255, 255, .012) 6px,
        transparent 6px, transparent 12px);
}

.hour-line[b-wf7y9hdcdc] {
    position: relative;
    height: 52px;
    border-top: 1px solid var(--glass-border);
    min-width: 0;
}

/* An hour with anything free is ONE target. It shows its time (or a count)
   normally, and swaps to a ＋ on hover — the same affordance the public page
   uses, which reads as "add something here" rather than "here is a label". */
/* A free hour is the only thing on this grid worth acting on, so it is the only
   thing with colour in it. Empty hours stay plain — that contrast is what lets
   the week be scanned at a glance instead of read cell by cell. */
.free-slot[b-wf7y9hdcdc] {
    cursor: pointer;
    background: color-mix(in srgb, var(--svc-pistachio) 11%, transparent);
    box-shadow: inset 2px 0 0 color-mix(in srgb, var(--svc-pistachio) 55%, transparent);
    transition: background .15s ease, box-shadow .15s ease;
}

.free-slot:hover[b-wf7y9hdcdc] {
    background: color-mix(in srgb, var(--svc-pistachio) 26%, transparent);
    box-shadow: inset 2px 0 0 var(--svc-pistachio);
}

.slot-time[b-wf7y9hdcdc] {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font-size: 12px;
    font-weight: 600;
    color: var(--svc-pistachio-lit);
    font-variant-numeric: tabular-nums;
    transition: opacity .15s ease;
}

/* The count is what the eye actually scans for — "how busy is Tuesday" — so it
   is set large, with the word small beneath it rather than sharing its weight. */
.slot-count[b-wf7y9hdcdc] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0;
    line-height: 1.05;
}

.sc-num[b-wf7y9hdcdc] {
    font-size: 19px;
    font-weight: 800;
    color: var(--svc-pistachio-lit);
}

.sc-word[b-wf7y9hdcdc] {
    font-size: 9px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: color-mix(in srgb, var(--svc-pistachio-lit) 75%, transparent);
}

.add-slot-icon[b-wf7y9hdcdc] {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(.6);
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--svc-pistachio);
    border: 1px solid color-mix(in srgb, var(--svc-pistachio-lit) 70%, transparent);
    box-shadow: 0 2px 10px color-mix(in srgb, var(--svc-pistachio) 55%, transparent);
    /* Dark ink on a light-green disc: the ＋ has to survive on top of a filled
       circle, where --text would vanish. */
    color: #0d1b16;
    font-size: 13px;
    font-weight: 700;
    opacity: 0;
    transition: opacity .15s ease, transform .15s ease;
    /* The click belongs to the whole cell; the icon must never swallow it. */
    pointer-events: none;
}

/* Swap: the time fades out, the ＋ grows in. */
.free-slot:hover .slot-time[b-wf7y9hdcdc] { opacity: 0; }

.free-slot:hover .add-slot-icon[b-wf7y9hdcdc] {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}

/* Touch has no hover, so the ＋ would never appear and the time would never
   leave. Show both states at rest instead of a swap that cannot happen. */
@media (hover: none) {
    .free-slot .slot-time[b-wf7y9hdcdc] { opacity: 1; }
    .free-slot .add-slot-icon[b-wf7y9hdcdc] { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .free-slot[b-wf7y9hdcdc],
    .slot-time[b-wf7y9hdcdc],
    .add-slot-icon[b-wf7y9hdcdc] { transition: none; }
}

/* ---------- Choosing a time inside the window ---------- */

.pick-lead[b-wf7y9hdcdc] {
    margin: 0 0 10px;
    font-size: 12px;
}

.time-picks[b-wf7y9hdcdc] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* Same green as the grid they were chosen from, so the window reads as a
   continuation of the click rather than a different screen. */
.time-pick[b-wf7y9hdcdc] {
    border: 1px solid color-mix(in srgb, var(--svc-pistachio) 40%, transparent);
    background: color-mix(in srgb, var(--svc-pistachio) 12%, transparent);
    color: var(--svc-pistachio-lit);
    border-radius: var(--radius-md);
    padding: 10px 16px;
    font-size: 14px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    font-family: inherit;
    cursor: pointer;
    transition: border-color .12s ease, background .12s ease, transform .12s ease;
}

.time-pick:hover[b-wf7y9hdcdc] {
    background: color-mix(in srgb, var(--svc-pistachio) 26%, transparent);
    border-color: var(--svc-pistachio);
    transform: translateY(-1px);
}

@media (prefers-reduced-motion: reduce) {
    .time-pick:hover[b-wf7y9hdcdc] { transform: none; }
}

/* The chosen time, kept on screen while the details are filled in. */
.picked-bar[b-wf7y9hdcdc] {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--glass-border);
}

.picked-time[b-wf7y9hdcdc] {
    font-size: 19px;
    font-weight: 800;
    color: var(--svc-pistachio-lit);
    font-variant-numeric: tabular-nums;
}

/* A link that is really a button: it steps back inside the dialog rather than
   navigating, and an <a href="#"> would jump the scroll. */
.linkish[b-wf7y9hdcdc] {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 12px;
    color: var(--text-dim);
    text-decoration: underline;
    cursor: pointer;
}

.linkish:hover[b-wf7y9hdcdc] { color: var(--text); }
.linkish:disabled[b-wf7y9hdcdc] { opacity: .5; cursor: default; }

@media (prefers-reduced-motion: reduce) {
    .time-pick[b-wf7y9hdcdc] { transition: none; }
}

.cal-note[b-wf7y9hdcdc] {
    margin: 10px 2px 0;
    font-size: 11px;
}

/* ---------- Details dialog ---------- */

.field[b-wf7y9hdcdc] { margin-bottom: 14px; }

.field .label[b-wf7y9hdcdc] {
    display: block;
    margin-bottom: 5px;
}

.area[b-wf7y9hdcdc] {
    resize: vertical;
    min-height: 54px;
    font-family: inherit;
}

.hint[b-wf7y9hdcdc] {
    display: block;
    margin-top: 5px;
    font-size: 11px;
    line-height: 1.5;
}

.check[b-wf7y9hdcdc] {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--text);
    cursor: pointer;
    padding: 4px 0 2px;
}

.check input[b-wf7y9hdcdc] { cursor: pointer; }

.sms-off[b-wf7y9hdcdc] {
    font-size: 11.5px;
    line-height: 1.6;
    padding: 4px 0 2px;
}

/* ---------- Narrow screens ---------- */

/* Below this the seven day columns are a few characters wide and the chips are
   unreadable. The grid scrolls sideways instead of compressing. */
@media (max-width: 860px) {
    .week-grid[b-wf7y9hdcdc] { overflow-x: auto; }

    .week-head[b-wf7y9hdcdc],
    .week-body[b-wf7y9hdcdc] {
        grid-template-columns: 46px repeat(7, minmax(84px, 1fr));
        min-width: 640px;
    }
}
/* /Components/Pages/NumberRequiredPanel.razor.rz.scp.css */
/* The full-page "choose your number" step.

   Sized and centred rather than stretched: a wall of text across a wide monitor
   reads as an error page, and this is not an error — it is the last step of
   signing up. */

.gate-wrap[b-hallfyr729] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60vh;
    padding: 32px 16px;
}

.gate-card[b-hallfyr729] {
    max-width: 560px;
    text-align: center;
    /* The panel's own surface token. --surface and --glass-bg do not exist here and
       a var() fallback would silently paint a hard colour that ignores the gold
       and lilac themes — a trap this codebase has hit before. */
    background: var(--glass-strong);
    border: 1px solid var(--glass-edge);
    border-radius: 18px;
    padding: 40px 36px;
    box-shadow: 0 18px 48px rgba(0, 0, 0, .22);
}

.gate-icon[b-hallfyr729] {
    font-size: 44px;
    line-height: 1;
    margin-bottom: 18px;
}

.gate-title[b-hallfyr729] {
    font-size: 22px;
    font-weight: 700;
    margin: 0 0 14px;
    color: var(--ink);
}

.gate-lead[b-hallfyr729] {
    font-size: 15px;
    line-height: 1.65;
    margin: 0 0 12px;
    color: var(--ink);
}

.gate-body[b-hallfyr729] {
    font-size: 14px;
    line-height: 1.65;
    margin: 0 0 16px;
    color: var(--ink-dim);
}

/* The consequence. Saffron rather than red: this is a step outstanding, not a
   fault, and a red panel would read as "your account is broken" to someone who
   has just paid us. */
.gate-warn[b-hallfyr729] {
    font-size: 13.5px;
    line-height: 1.6;
    margin: 0 0 22px;
    padding: 12px 14px;
    border-radius: 10px;
    background: rgba(233, 161, 59, .12);
    border: 1px solid rgba(233, 161, 59, .32);
    color: var(--ink);
}

.btn-lg[b-hallfyr729] {
    font-size: 15px;
    padding: 12px 26px;
}

.gate-foot[b-hallfyr729] {
    margin: 20px 0 0;
    font-size: 12.5px;
}

.gate-foot a[b-hallfyr729] {
    color: inherit;
    text-decoration: underline;
}

@media (max-width: 520px) {
    .gate-card[b-hallfyr729] { padding: 30px 22px; }
    .gate-title[b-hallfyr729] { font-size: 19px; }
}

/* The purchase card, dropped into the middle of a centred wall.

   LEFT-ALIGNED inside a centred page: the copy above is a short announcement
   and reads well centred, but the card holds labels, a text input and a list of
   numbers — form controls centred in their own box look broken, and a column of
   centred phone numbers is genuinely harder to scan than a left-aligned one.

   The nested card also loses its own frame. It sits inside .gate-card, and a
   panel inside an identical panel reads as a rendering mistake rather than as
   one step. */
.gate-buy[b-hallfyr729] {
    margin: 4px 0 4px;
    text-align: left;
}

.gate-buy[b-hallfyr729]  .card {
    background: none;
    border: none;
    box-shadow: none;
    padding: 0;
}

.gate-buy[b-hallfyr729]  .card-head {
    /* "Your phone number" restates the heading two lines above it. */
    display: none;
}

.gate-buy[b-hallfyr729]  .card-body {
    padding: 0;
}
/* /Components/Pages/Plans.razor.rz.scp.css */
/* ============================================================
   Plans.razor.css — the public pricing page.

   Scoped by Blazor's CSS isolation. Every colour comes from
   theme.css, so this page follows blue/gold/lilac like the rest
   of the panel rather than pinning its own palette.

   .card / .badge and friends live in app.css but are tuned for
   dense admin tables; a shop window wants air, so the surfaces
   here are their own classes built from the same tokens.
   ============================================================ */

.plans-shell[b-5t4q6x5bwl] {
    min-height: 100vh;
    padding: 2.5rem 1.5rem 4rem;
    color: var(--ink);
    /* This page is reached with no layout chrome (EmptyLayout), so it paints
       its own ground — otherwise it inherits the browser's white. */
    background: var(--bg-gradient);
    background-attachment: fixed;
}

/* ---------- Header ---------- */

.plans-head[b-5t4q6x5bwl] {
    max-width: 1120px;
    margin: 0 auto 2.5rem;
}

.plans-brand[b-5t4q6x5bwl] {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    color: inherit;
}

.plans-logo[b-5t4q6x5bwl] {
    width: 42px;
    height: 42px;
    object-fit: contain;
    filter: drop-shadow(0 0 9px var(--accent-glow));
}

.brand-name[b-5t4q6x5bwl] {
    font-size: 16px;
    font-weight: 700;
}

.brand-tag[b-5t4q6x5bwl] {
    font-size: 12px;
    color: var(--ink-dim);
}

/* ---------- Intro ---------- */

.plans-intro[b-5t4q6x5bwl] {
    max-width: 640px;
    margin: 0 auto 2.5rem;
    text-align: center;
}

.plans-intro h1[b-5t4q6x5bwl] {
    font-size: clamp(28px, 4vw, 40px);
    line-height: 1.2;
    margin: 0 0 12px;
}

.plans-intro p[b-5t4q6x5bwl] {
    margin: 0;
    font-size: 15px;
    line-height: 1.8;
    color: var(--ink-muted, var(--text-dim));
}

.plans-empty[b-5t4q6x5bwl] {
    max-width: 560px;
    margin: 0 auto;
    padding: 2rem;
    text-align: center;
    font-size: 14px;
    color: var(--text-faint);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-xl);
}

.plans-empty a[b-5t4q6x5bwl] { color: var(--text-dim); }

/* ---------- Included in every plan ---------- */

.included[b-5t4q6x5bwl] {
    max-width: 1120px;
    margin: 3.5rem auto 0;
}

.included-head[b-5t4q6x5bwl] {
    text-align: center;
    margin-bottom: 1.75rem;
}

.included-head h2[b-5t4q6x5bwl] {
    font-size: 22px;
    margin: 0 0 6px;
}

.included-head p[b-5t4q6x5bwl] {
    margin: 0;
    font-size: 13.5px;
    color: var(--text-faint);
}

.included-grid[b-5t4q6x5bwl] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 18px;
}

.inc-group[b-5t4q6x5bwl] {
    padding: 22px 24px;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
}

.inc-title[b-5t4q6x5bwl] {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-dim);
    margin-bottom: 14px;
}

.inc-list[b-5t4q6x5bwl] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 13px;
}

.inc-list li[b-5t4q6x5bwl] {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    font-size: 13.5px;
    line-height: 1.55;
}

.tick[b-5t4q6x5bwl] {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    margin-top: 1px;
    display: grid;
    place-items: center;
    font-size: 11px;
    font-weight: 700;
    border-radius: 50%;
    color: var(--accent-text-on-fill);
    background: var(--accent-gradient);
}

.inc-list strong[b-5t4q6x5bwl] {
    display: block;
    font-weight: 600;
    color: var(--ink);
}

.inc-note[b-5t4q6x5bwl] {
    display: block;
    margin-top: 2px;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--text-faint);
}

/* ---------- Foot ---------- */

.plans-foot[b-5t4q6x5bwl] {
    max-width: 640px;
    margin: 3rem auto 0;
    text-align: center;
    font-size: 12.5px;
    line-height: 1.8;
    color: var(--text-faint);
}

.plans-foot a[b-5t4q6x5bwl] { color: var(--text-dim); }

/* ---------- Responsive ---------- */

@media (max-width: 640px) {
    .plans-shell[b-5t4q6x5bwl] { padding: 1.75rem 1rem 3rem; }
}

/* The card rules — including their responsive and reduced-motion variants —
   live in PlanCards.razor.css. Blazor's isolation attribute is per COMPONENT,
   so a rule written here cannot reach markup the child renders; keeping a copy
   here would style nothing while looking like it did. */
/* /Components/Pages/Products.razor.rz.scp.css */
.page-header[b-1d5z2lmbp3] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

.page-title[b-1d5z2lmbp3] { font-size: 17px; font-weight: 700; }

.page-sub[b-1d5z2lmbp3] {
    font-size: 12px;
    color: var(--text-dim);
    margin-top: 2px;
    max-width: 62ch;
}

/* ---------- Stat cards: same glass as everywhere ---------- */

/* Five across, one row. The grid still said repeat(3) from when there were
   three tiles, so the two new ones wrapped onto a second row and pushed the
   catalogue below the fold. */
.stats-grid[b-1d5z2lmbp3] {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 10px;
    margin-bottom: 14px;
}

/* Below a laptop, five tiles each get ~180px and the labels wrap to three
   lines — worse than two clean rows. */
@media (max-width: 1250px) {
    .stats-grid[b-1d5z2lmbp3] { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 780px) {
    .stats-grid[b-1d5z2lmbp3] { grid-template-columns: repeat(2, 1fr); }
}

.stat-card[b-1d5z2lmbp3] {
    position: relative;
    padding: 13px 14px;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    overflow: hidden;
    box-shadow: var(--shadow), 0 0 22px var(--accent-glow-soft);
    transition: transform 0.2s;
}

.stat-card:hover[b-1d5z2lmbp3] { transform: translateY(-2px); }

/* The lit top edge, as on every other surface. */
.stat-card[b-1d5z2lmbp3]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-border) 45%, transparent);
    pointer-events: none;
}

/* Tints layer over the theme's own glass, never over black. */
.stat-blue[b-1d5z2lmbp3] { background: linear-gradient(160deg, var(--accent-glow-soft), var(--glass-bg)); }
.stat-green[b-1d5z2lmbp3] { background: linear-gradient(160deg, rgba(74, 222, 128, 0.13), var(--glass-bg)); }
.stat-amber[b-1d5z2lmbp3] { background: linear-gradient(160deg, rgba(233, 161, 59, 0.17), var(--glass-bg)); border-color: rgba(233, 161, 59, 0.32); }

/* Defined here, not reused: the Dashboard's and Calls' stat-cyan live in THEIR
   scoped css, which does not cross components — copied markup renders unstyled. */
.stat-cyan[b-1d5z2lmbp3] { background: linear-gradient(160deg, rgba(34, 211, 238, 0.13), var(--glass-bg)); }

/* Red only when something needs reordering — an always-red tile is wallpaper. */
.stat-red[b-1d5z2lmbp3] {
    background: linear-gradient(160deg, rgba(248, 113, 113, 0.15), var(--glass-bg));
    border-color: rgba(248, 113, 113, 0.32);
}

/* Faint on purpose: the icon tells you which tile you are on at a glance, and
   then gets out of the way of the number, which is the thing being read. */
.stat-icon-top[b-1d5z2lmbp3] {
    position: absolute;
    top: 10px;
    right: 12px;
    font-size: 14px;
    opacity: 0.38;
    pointer-events: none;
}

.stat-val[b-1d5z2lmbp3] {
    font-size: 19px;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.02em;
    color: var(--text-main);
    /* Room for the icon, so a five-figure number never runs under it. */
    padding-right: 20px;
}

.stat-lbl[b-1d5z2lmbp3] {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-dim);
    margin-top: 2px;
}

.stat-meta[b-1d5z2lmbp3] { font-size: 10px; color: var(--text-faint); margin-top: 4px; }

/* ---------- Table ---------- */

.price[b-1d5z2lmbp3] { color: #F2BE72 !important; font-weight: 700; }
.margin[b-1d5z2lmbp3] { color: #86EFAC; font-weight: 700; }
.margin-pct[b-1d5z2lmbp3] { margin-left: 5px; font-size: 10.5px; }
.stock-ok[b-1d5z2lmbp3] { color: var(--text-main); font-weight: 600; }

.actions[b-1d5z2lmbp3] { display: flex; gap: 5px; }

.actions .btn[b-1d5z2lmbp3] { padding: 4px 10px; font-size: 11.5px; }

/* Four actions, four meanings, four colours. As one uniform ghost row, "Sell"
   and "Delete" read as equally likely — on a table where one takes money and the
   other destroys a product the owner priced and stocked. */
.btn-sell[b-1d5z2lmbp3] {
    background: rgba(74, 222, 128, 0.16);
    border-color: rgba(74, 222, 128, 0.36);
    color: #86EFAC;
}

.btn-sell:hover:not(:disabled)[b-1d5z2lmbp3] { background: rgba(74, 222, 128, 0.3); }

/* Restocking spends money with a supplier, so it wears the money colour. */
.btn-restock[b-1d5z2lmbp3] {
    background: rgba(233, 161, 59, 0.15);
    border-color: rgba(233, 161, 59, 0.34);
    color: #F5C97B;
}

.btn-restock:hover[b-1d5z2lmbp3] { background: rgba(233, 161, 59, 0.28); }

.btn-edit[b-1d5z2lmbp3] {
    background: rgba(35, 80, 155, 0.2);
    border-color: rgba(78, 134, 224, 0.32);
    color: #9CC4FF;
}

.btn-edit:hover[b-1d5z2lmbp3] { background: rgba(35, 80, 155, 0.34); }

/* Deleting stays quiet until reached for — loud red among four buttons invites
   the mis-click it is warning about. It turns red on hover, where the intent is
   already formed. */
.btn-drop[b-1d5z2lmbp3] {
    background: transparent;
    border-color: var(--glass-border);
    color: var(--text-faint);
}

.btn-drop:hover[b-1d5z2lmbp3] {
    background: rgba(180, 55, 47, 0.18);
    border-color: rgba(255, 138, 138, 0.4);
    color: #FFB4B4;
}

.danger-text[b-1d5z2lmbp3] { color: var(--text-error); }
.danger-text:hover[b-1d5z2lmbp3] { background: rgba(180, 55, 47, 0.14); border-color: transparent; }

/* ---------- Forms ---------- */

.pair[b-1d5z2lmbp3] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.hint[b-1d5z2lmbp3] { font-size: 10.5px; }

/* Live arithmetic: the owner types cost and price, this shows the margin. */
.preview[b-1d5z2lmbp3] {
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-wrap: wrap;
    padding: 10px 13px;
    font-size: 12px;
    background: var(--accent-glow-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
}

.preview strong[b-1d5z2lmbp3] { color: var(--text-main); font-size: 14px; }

.confirm[b-1d5z2lmbp3] { font-size: 12.5px; line-height: 1.7; color: var(--text-dim); }
.confirm strong[b-1d5z2lmbp3] { color: var(--text-main); }

@media (max-width: 900px) {
    .stats-grid[b-1d5z2lmbp3] { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
    .pair[b-1d5z2lmbp3] { grid-template-columns: 1fr; }
}

/* The import-mode choice (Add / Replace). Its own label per option, not a
   dropdown: "Replace existing" is close to irreversible in effect, and a
   sentence beside the button a person actually reads is safer here than a
   two-word option they might tap past. */
.radio-row[b-1d5z2lmbp3] {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 8px 0;
    font-size: 12.5px;
    color: var(--text-dim);
    cursor: pointer;
}

.radio-row input[type="radio"][b-1d5z2lmbp3] {
    margin-top: 2px;
    flex-shrink: 0;
}
/* /Components/Pages/PublicSite.razor.rz.scp.css */
/* The business's public page. Same glass language as the panel, but calmer:
   a customer reads this once on a phone, they don't operate it daily.

   data-theme on .site (not <html>) so each business picks its own look while
   the panel around it keeps the owner's. */

.site[b-xxbada20gp] {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bg-gradient);
    color: var(--text-main);
}

/* ---------- Banner + header ---------- */

.banner[b-xxbada20gp] {
    height: 220px;
    background-size: cover;
    background-position: center;
    position: relative;
}

/* A scrim: the banner is an owner-supplied photo of anything, and the header
   below has to stay readable over it. */
.banner[b-xxbada20gp]::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, transparent 30%, var(--bg-gradient));
}

.head[b-xxbada20gp] {
    display: flex;
    align-items: center;
    gap: 18px;
    max-width: 780px;
    width: 100%;
    margin: -54px auto 0;
    padding: 0 20px 24px;
    position: relative;
    z-index: 1;
}

.head-plain[b-xxbada20gp] { margin-top: 44px; }

.logo[b-xxbada20gp] {
    width: 92px;
    height: 92px;
    flex-shrink: 0;
    object-fit: cover;
    border-radius: var(--radius-lg);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    box-shadow: 0 0 25px var(--accent-glow-soft);
}

.head-text[b-xxbada20gp] { min-width: 0; }

.head h1[b-xxbada20gp] {
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.slogan[b-xxbada20gp] {
    margin-top: 4px;
    font-size: 14px;
    color: var(--text-dim);
}

/* ---------- Status ---------- */

.status[b-xxbada20gp] {
    max-width: 780px;
    width: 100%;
    margin: 0 auto 16px;
    padding: 12px 16px;
    border-radius: var(--radius-md);
    font-size: 14px;
    border: 1px solid transparent;
}

.status-ok[b-xxbada20gp] { color: #86EFAC; background: rgba(74, 222, 128, 0.14); border-color: rgba(74, 222, 128, 0.35); }
.status-bad[b-xxbada20gp] { color: var(--text-error); background: rgba(180, 55, 47, 0.16); border-color: rgba(255, 138, 138, 0.4); }

/* ---------- Body ---------- */

.body[b-xxbada20gp] {
    flex: 1;
    width: 100%;
    max-width: 780px;
    margin: 0 auto;
    padding: 0 20px 40px;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.block[b-xxbada20gp] {
    padding: 20px 22px;
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
}

.block h2[b-xxbada20gp] {
    font-size: 15px;
    font-weight: 700;
    margin-bottom: 14px;
}

.about[b-xxbada20gp] {
    font-size: 14px;
    line-height: 1.75;
    color: var(--text-dim);
    /* Running text stays near 65 characters — the block is wider than that. */
    max-width: 65ch;
}

/* ---------- Service cards ---------- */

.cards[b-xxbada20gp] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 10px;
}

/* The whole card is the target — a customer aiming at a small "Book" link on a
   phone is a customer who misses. */
.scard[b-xxbada20gp] {
    display: grid;
    grid-template-areas:
        "name  price"
        "meta  go";
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 6px 10px;
    padding: 14px 15px;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    font-family: inherit;
    text-align: left;
    color: inherit;
    cursor: pointer;
    transition: border-color .15s ease, transform .15s ease, background .15s ease;
}

/* The chosen service stays lit after the pointer leaves — on a grid of cards,
   "which one did I pick?" must be answerable without hovering again. */
.scard-on[b-xxbada20gp] {
    border-color: var(--accent-glow);
    background: var(--accent-glow-soft);
}

.scard-on .sc-go[b-xxbada20gp] { opacity: 1; color: var(--text-main); }

.scard:hover[b-xxbada20gp], .scard:focus-visible[b-xxbada20gp] {
    border-color: var(--accent-glow);
    background: var(--glass-bg);
    transform: translateY(-2px);
}

.sc-name[b-xxbada20gp] {
    grid-area: name;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-main);
}

.sc-meta[b-xxbada20gp] {
    grid-area: meta;
    font-size: 11.5px;
    color: var(--text-faint);
}

.sc-price[b-xxbada20gp] {
    grid-area: price;
    font-size: 15px;
    font-weight: 700;
    color: #F2BE72;
    text-align: right;
}

/* The affordance stays quiet until the card is aimed at: on a grid of cards,
   eight shouting "Book →" is noise, not guidance. */
.sc-go[b-xxbada20gp] {
    grid-area: go;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-dim);
    text-align: right;
    opacity: 0;
    transition: opacity .15s ease;
}

.scard:hover .sc-go[b-xxbada20gp], .scard:focus-visible .sc-go[b-xxbada20gp] { opacity: 1; }

/* Touch has no hover, so the hint would never appear — show it always. */
@media (hover: none) {
    .sc-go[b-xxbada20gp] { opacity: 1; }
}

/* ---------- Hours ---------- */

.hours[b-xxbada20gp] { list-style: none; display: flex; flex-direction: column; gap: 1px; }

.hrow[b-xxbada20gp] {
    display: flex;
    justify-content: space-between;
    padding: 7px 10px;
    font-size: 13px;
    color: var(--text-dim);
    border-radius: var(--radius-sm);
}

/* Today is lit — the one row a customer is actually looking for. */
.hrow-today[b-xxbada20gp] {
    color: var(--text-main);
    font-weight: 600;
    background: var(--accent-glow-soft);
}

/* ---------- Gallery ---------- */

.gallery[b-xxbada20gp] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
}

.shot[b-xxbada20gp] { margin: 0; }

.shot img[b-xxbada20gp] {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    display: block;
}

/* The login slides' caption panel, borrowed: frosted glass with a gradient
   hairline. Sits under its photo rather than over it — see the markup. */
.shot-cap[b-xxbada20gp] {
    position: relative;
    margin-top: 8px;
    padding: 9px 11px;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    background: var(--glass-bg-soft);
    background-clip: padding-box;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    font-size: 11.5px;
    line-height: 1.6;
    color: var(--text-dim);
}

/* The gradient border trick from the login slides: a 1px inset painted with the
   accent, masked so only the ring shows. */
.shot-cap[b-xxbada20gp]::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--radius-md);
    padding: 1px;
    background: var(--accent-gradient);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    opacity: .5;
    pointer-events: none;
}

/* ---------- Booking form ---------- */

.bform[b-xxbada20gp] { display: flex; flex-direction: column; gap: 14px; }

.brow[b-xxbada20gp] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.f[b-xxbada20gp] { display: flex; flex-direction: column; gap: 5px; }

.fl[b-xxbada20gp] { font-size: 12px; font-weight: 600; color: var(--text-dim); }

.fi[b-xxbada20gp] {
    width: 100%;
    padding: 11px 12px;
    font-family: inherit;
    font-size: 14px;
    color: var(--text-main);
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    outline: none;
    color-scheme: dark;
    transition: border-color 0.25s, box-shadow 0.25s;
}

.fi:focus[b-xxbada20gp] {
    border-color: var(--text-dim);
    box-shadow: 0 0 12px var(--accent-glow-soft);
}

/* The honeypot. Off-screen rather than display:none — some bots skip hidden
   fields, but they fill this one. aria-hidden and tabindex="-1" in the markup
   keep it away from screen readers and the keyboard, so no real visitor sees it. */
.hp[b-xxbada20gp] {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.bsubmit[b-xxbada20gp] {
    padding: 13px;
    font-family: inherit;
    font-size: 15px;
    font-weight: 700;
    color: var(--accent-text-on-fill);
    background: var(--accent-gradient);
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    box-shadow: 0 0 18px var(--accent-glow-soft);
    transition: transform 0.2s, box-shadow 0.2s;
}

.bsubmit:hover[b-xxbada20gp] { transform: translateY(-2px); box-shadow: 0 0 25px var(--accent-glow); }
.bsubmit:active[b-xxbada20gp] { transform: translateY(0); }

.bnote[b-xxbada20gp] { font-size: 11px; color: var(--text-faint); text-align: center; }

.fhint[b-xxbada20gp] { font-size: 11px; }

/* ---------- Calendar toolbar ---------- */

.toolbar[b-xxbada20gp] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 10px 12px;
    margin-bottom: 14px;
    border-radius: var(--radius-lg);
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    backdrop-filter: blur(18px);
}

.view-switch[b-xxbada20gp] {
    display: flex;
    gap: 2px;
    padding: 3px;
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.03);
}

.view-btn[b-xxbada20gp] {
    padding: 6px 14px;
    border: none;
    border-radius: 6px;
    background: transparent;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-faint);
    cursor: pointer;
    transition: .15s;
}

.view-btn.active[b-xxbada20gp] { background: var(--accent-glow-soft); color: var(--text-main); }
.view-btn:hover:not(.active)[b-xxbada20gp] { color: var(--text-dim); }

.date-nav[b-xxbada20gp] { display: flex; align-items: center; gap: 6px; }

.nav-btn[b-xxbada20gp] {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: transparent;
    color: var(--text-dim);
    font-size: 15px;
    cursor: pointer;
    transition: .15s;
}

.nav-btn:hover[b-xxbada20gp] { background: var(--accent-glow-soft); color: var(--text-main); }

.date-label[b-xxbada20gp] {
    min-width: 168px;
    text-align: center;
    font-size: 13px;
    font-weight: 700;
}

.today-btn[b-xxbada20gp] {
    padding: 6px 12px;
    border-radius: var(--radius-md);
    border: 1px solid var(--accent-glow);
    background: var(--accent-glow-soft);
    color: var(--text-main);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}

.toolbar-spacer[b-xxbada20gp] { flex: 1; }

.filter-select[b-xxbada20gp] {
    padding: 7px 11px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text-main);
    font-family: inherit;
    font-size: 12px;
    outline: none;
}

.cal-loading[b-xxbada20gp], .cal-note[b-xxbada20gp] {
    padding: 14px;
    font-size: 12px;
    color: var(--text-dim);
    text-align: center;
}

/* ---------- Week grid ---------- */

.week-grid[b-xxbada20gp] {
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    backdrop-filter: blur(14px);
}

.week-head[b-xxbada20gp] {
    display: grid;
    grid-template-columns: 54px repeat(7, 1fr);
    border-bottom: 1px solid var(--glass-border);
}

.week-head-cell[b-xxbada20gp] {
    padding: 9px 4px;
    text-align: center;
    border-left: 1px solid var(--glass-border);
}

.week-head-cell:first-child[b-xxbada20gp] { border-left: none; }

.wh-day[b-xxbada20gp] {
    font-size: 10px;
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: .5px;
}

.wh-date[b-xxbada20gp] { font-size: 15px; font-weight: 700; margin-top: 2px; }

.week-head-cell.is-today .wh-date[b-xxbada20gp] {
    display: inline-grid;
    place-items: center;
    width: 25px;
    height: 25px;
    border-radius: 50%;
    background: var(--accent-glow-soft);
    color: var(--text-main);
}

.week-body[b-xxbada20gp] {
    display: grid;
    grid-template-columns: 54px repeat(7, 1fr);
    max-height: 560px;
    overflow-y: auto;
}

.week-body[b-xxbada20gp]::-webkit-scrollbar { width: 5px; }
.week-body[b-xxbada20gp]::-webkit-scrollbar-thumb { background: var(--glass-border); border-radius: 5px; }

.time-col[b-xxbada20gp] { display: flex; flex-direction: column; }

.time-slot[b-xxbada20gp] {
    height: 52px;
    padding: 2px 5px 0 0;
    border-top: 1px solid rgba(255, 255, 255, 0.05);
    font-size: 10px;
    color: var(--text-faint);
    text-align: right;
    transform: translateY(-7px);
}

.day-col[b-xxbada20gp] { border-left: 1px solid var(--glass-border); }
.day-col.is-today[b-xxbada20gp] { background: var(--accent-glow-soft); }

/* Past days are struck through with hatching rather than hidden: the week must
   still read as a week. */
.day-col.is-past[b-xxbada20gp] {
    background: repeating-linear-gradient(45deg,
        rgba(255, 255, 255, .012), rgba(255, 255, 255, .012) 6px,
        transparent 6px, transparent 12px);
}

.hour-line[b-xxbada20gp] {
    position: relative;
    height: 52px;
    border-top: 1px solid rgba(255, 255, 255, 0.05);
}

/* A free hour is the whole point of the grid — it is the button. */
.free-slot[b-xxbada20gp] { cursor: pointer; transition: background .15s; }
.free-slot:hover[b-xxbada20gp] { background: var(--accent-glow-soft); }

.slot-time[b-xxbada20gp] {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-dim);
    transition: opacity .15s;
}

.add-slot-icon[b-xxbada20gp] {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(.6);
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--accent-glow-soft);
    border: 1px solid var(--accent-glow);
    color: var(--text-main);
    font-size: 13px;
    font-weight: 700;
    opacity: 0;
    transition: .15s;
    pointer-events: none;
}

/* The time swaps for a + on hover: the cell says WHAT it is at rest and WHAT
   IT DOES when aimed at. */
.free-slot:hover .add-slot-icon[b-xxbada20gp] { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.free-slot:hover .slot-time[b-xxbada20gp] { opacity: 0; }

/* Touch has no hover — keep the time, drop the +. */
@media (hover: none) {
    .add-slot-icon[b-xxbada20gp] { display: none; }
    .free-slot .slot-time[b-xxbada20gp] { opacity: 1; }
}

/* ---------- Month grid ---------- */

.month-grid[b-xxbada20gp] {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    backdrop-filter: blur(14px);
}

.month-head-cell[b-xxbada20gp] {
    padding: 8px;
    text-align: center;
    font-size: 10px;
    font-weight: 600;
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: .5px;
    border-bottom: 1px solid var(--glass-border);
}

.month-day-cell[b-xxbada20gp] {
    min-height: 84px;
    padding: 6px;
    border-right: 1px solid rgba(255, 255, 255, 0.05);
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.month-day-cell.other-month[b-xxbada20gp] { opacity: .3; }
.month-day-cell.is-past[b-xxbada20gp] { opacity: .45; }
.month-day-cell.is-today[b-xxbada20gp] { background: var(--accent-glow-soft); }
.month-day-cell.has-free[b-xxbada20gp] { cursor: pointer; transition: background .15s; }
.month-day-cell.has-free:hover[b-xxbada20gp] { background: var(--glass-bg); }

.mdc-num[b-xxbada20gp] { font-size: 12px; font-weight: 600; color: var(--text-dim); }

.month-day-cell.is-today .mdc-num[b-xxbada20gp] {
    display: inline-grid;
    place-items: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--accent-gradient);
    color: var(--accent-text-on-fill);
}

/* A count, not a list of times: thirty cells of times is a wall. */
.mdc-free[b-xxbada20gp] {
    margin-top: 5px;
    padding: 3px 6px;
    border-radius: var(--radius-sm);
    background: var(--accent-glow-soft);
    border-left: 2px solid var(--accent-glow);
    font-size: 10px;
    font-weight: 600;
    color: var(--text-dim);
}

.mdc-none[b-xxbada20gp] { margin-top: 5px; font-size: 10px; color: var(--text-faint); }

/* ---------- Slot list (day sheet) ---------- */

.slots[b-xxbada20gp] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
    gap: 7px;
}

.slot[b-xxbada20gp] {
    padding: 10px 4px;
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 600;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text-main);
    cursor: pointer;
    transition: border-color .15s, transform .15s, background .15s;
}

.slot:hover[b-xxbada20gp] {
    border-color: var(--accent-glow);
    background: var(--glass-bg);
    transform: translateY(-2px);
}

/* ---------- Dialogs ---------- */

.overlay[b-xxbada20gp] {
    position: fixed;
    inset: 0;
    z-index: 199;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(2px);
}

/* Both dialogs share the frame. A side panel on the desktop, a bottom sheet on
   a phone — see the media query. */
.sheet-panel[b-xxbada20gp], .book-panel[b-xxbada20gp] {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 200;
    width: 420px;
    max-width: 100vw;
    display: flex;
    flex-direction: column;
    background: var(--glass-bg);
    backdrop-filter: blur(24px);
    border-left: 1px solid var(--glass-border);
    animation: slide-in-b-xxbada20gp .22s ease;
}

@keyframes slide-in-b-xxbada20gp {
    from { transform: translateX(100%); }
    to { transform: translateX(0); }
}

.dp-head[b-xxbada20gp] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--glass-border);
}

.dp-title[b-xxbada20gp] { font-size: 15px; font-weight: 700; }
.dp-sub[b-xxbada20gp] { font-size: 11.5px; color: var(--text-dim); margin-top: 3px; }

.dp-close[b-xxbada20gp] {
    margin-left: auto;
    width: 30px;
    height: 30px;
    flex: none;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: transparent;
    color: var(--text-dim);
    font-size: 14px;
    cursor: pointer;
}

.dp-close:hover[b-xxbada20gp] { background: var(--accent-glow-soft); color: var(--text-main); }

.dp-body[b-xxbada20gp] {
    flex: 1;
    overflow-y: auto;
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* On a phone a 420px side panel is the whole screen anyway — make it a sheet,
   which is the gesture people expect there. */
@media (max-width: 560px) {
    .sheet-panel[b-xxbada20gp], .book-panel[b-xxbada20gp] {
        top: auto;
        left: 0;
        width: 100%;
        max-height: 88vh;
        border-left: none;
        border-top: 1px solid var(--glass-border);
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        animation: slide-up-b-xxbada20gp .22s ease;
    }

    @keyframes slide-up-b-xxbada20gp {
        from { transform: translateY(100%); }
        to { transform: translateY(0); }
    }
}

/* ---------- Chosen summary + confirmation ---------- */

.chosen[b-xxbada20gp] {
    font-size: 12.5px;
    line-height: 1.7;
    color: var(--text-dim);
    padding: 10px 12px;
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
}

.chosen strong[b-xxbada20gp] { color: var(--text-main); }

/* A button that reads as a link: it changes a step, so it must be a button for
   the keyboard and a link for the eye. */
.link-btn[b-xxbada20gp] {
    background: none;
    border: none;
    padding: 0 2px;
    font-family: inherit;
    font-size: 12px;
    color: var(--text-dim);
    text-decoration: underline;
    cursor: pointer;
}

.link-btn:hover[b-xxbada20gp] { color: var(--text-main); }

.code-f[b-xxbada20gp] { align-items: center; }

/* The code is the only thing on this step — let it be big enough to check at a
   glance against the phone in the other hand. */
.code-in[b-xxbada20gp] {
    max-width: 220px;
    text-align: center;
    font-size: 26px;
    font-weight: 700;
    letter-spacing: 0.32em;
    text-indent: 0.32em;
}

.done[b-xxbada20gp] { text-align: center; padding: 10px 0 4px; }

.done-tick[b-xxbada20gp] {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    margin: 0 auto 12px;
    border-radius: 50%;
    font-size: 26px;
    color: #04240f;
    background: var(--color-success);
}

.done h3[b-xxbada20gp] { font-size: 17px; margin-bottom: 8px; }
.done p[b-xxbada20gp] { font-size: 13.5px; line-height: 1.8; color: var(--text-dim); }
.done .bnote[b-xxbada20gp] { margin-top: 10px; }

/* ---------- Footer ---------- */

.foot[b-xxbada20gp] {
    padding: 24px 20px 32px;
    border-top: 1px solid var(--glass-border);
    text-align: center;
}

.contact[b-xxbada20gp] {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px 20px;
    margin-bottom: 14px;
}

.c-item[b-xxbada20gp] {
    font-size: 13px;
    color: var(--text-dim);
    text-decoration: none;
}

.c-item:hover[b-xxbada20gp] { color: var(--text-main); }

/* The phone number is the point of the whole product — give it weight. */
.c-call[b-xxbada20gp] { font-weight: 700; color: var(--text-main); }

.powered[b-xxbada20gp] { font-size: 11px; color: var(--text-faint); }

.missing[b-xxbada20gp] {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 20px;
    text-align: center;
    background: var(--bg-gradient);
    color: var(--text-main);
}

.missing p[b-xxbada20gp] { font-size: 14px; color: var(--text-dim); }

@media (max-width: 620px) {
    .banner[b-xxbada20gp] { height: 150px; }
    .head[b-xxbada20gp] { flex-direction: column; text-align: center; gap: 12px; }
    .logo[b-xxbada20gp] { width: 76px; height: 76px; }
    .brow[b-xxbada20gp] { grid-template-columns: 1fr; }
}
/* /Components/Pages/ResetPassword.razor.rz.scp.css */
/* Password-reset pages.
 *
 * These rules are DUPLICATED from Login.razor.css rather than shared, because
 * Blazor's scoped CSS does not cross components: markup copied from the login
 * page renders completely unstyled here. Only the parts these pages actually use
 * are copied — the card, the form panel, the inputs and the button — not the
 * slideshow half.
 *
 * ResetPassword.razor.css is deliberately identical. Two small copies beat a
 * shared global stylesheet that any page could then depend on by accident.
 */

.login-page[b-bk0as8u2mp] {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
    background: var(--bg-gradient);
}

.card[b-bk0as8u2mp] {
    width: min(940px, 100%);
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border: 1px solid var(--glass-border);
    box-shadow: 0 26px 70px rgba(0, 0, 0, 0.55), 0 0 25px var(--accent-glow-soft);
    border-radius: var(--radius-xl);
    overflow: hidden;
    position: relative;
    z-index: 2;
}

/* One column, unlike the login card's two: there is no slideshow here, and a
   half-empty 940px card reads as a broken page. */
.card.auth-narrow[b-bk0as8u2mp] {
    width: min(440px, 100%);
}

.left[b-bk0as8u2mp] {
    padding: 40px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.logo-row[b-bk0as8u2mp] {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
}

.logo-icon[b-bk0as8u2mp] {
    width: 34px;
    height: 34px;
    border-radius: 9px;
    background: var(--accent-glow-soft);
    border: 1px solid var(--glass-border);
    flex: none;
}

.logo-text-title[b-bk0as8u2mp] {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.2;
}

.logo-text-sub[b-bk0as8u2mp] {
    font-size: 11px;
    color: var(--text-dim);
}

.left h1[b-bk0as8u2mp] {
    font-size: 22px;
    font-weight: 700;
    color: var(--text);
    margin: 4px 0 0;
}

.auth-note[b-bk0as8u2mp] {
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-dim);
    margin: 0;
}

.auth-note strong[b-bk0as8u2mp] {
    color: var(--text);
    font-weight: 600;
    /* A long address must not push the card wider than the viewport. */
    word-break: break-word;
}

.form[b-bk0as8u2mp] {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 6px;
}

.left input[b-bk0as8u2mp] {
    width: 100%;
    padding: 11px 13px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
}

.left input[b-bk0as8u2mp]::placeholder { color: var(--text-faint); }

.left input:focus[b-bk0as8u2mp] {
    outline: none;
    border-color: var(--text-dim);
}

.left button[b-bk0as8u2mp] {
    width: 100%;
    padding: 11px 16px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: transform .12s ease, border-color .12s ease;
}

.left button:hover:not(:disabled)[b-bk0as8u2mp] {
    transform: translateY(-1px);
    border-color: var(--text-dim);
}

.left button:active:not(:disabled)[b-bk0as8u2mp] { transform: translateY(0); }

.left button:disabled[b-bk0as8u2mp] {
    opacity: .45;
    cursor: default;
}

.alert-box[b-bk0as8u2mp] {
    padding: 0.6rem 0.8rem;
    border-radius: var(--radius-md);
    font-size: 13px;
    color: var(--text-error);
    background: rgba(180, 55, 47, 0.16);
    border: 1px solid rgba(217, 86, 76, 0.4);
}

/* A link that looks like a link but is a button — it changes state on this page
   rather than navigating, and a real <a href="#"> would jump the scroll. */
.linkish[b-bk0as8u2mp] {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--text);
    text-decoration: underline;
    cursor: pointer;
    width: auto !important;
}

.auth-back[b-bk0as8u2mp] {
    margin-top: 6px;
    font-size: 12px;
    color: var(--text-dim);
    text-decoration: none;
}

.auth-back:hover[b-bk0as8u2mp] { text-decoration: underline; }

.btn-primary-link[b-bk0as8u2mp] {
    display: block;
    text-align: center;
    padding: 11px 16px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    margin-top: 6px;
}

.btn-primary-link:hover[b-bk0as8u2mp] { border-color: var(--text-dim); }

/* Live password guidance. Reads as "still needed" rather than as an error —
   nobody has done anything wrong yet while they are still typing. */
.auth-rules[b-bk0as8u2mp] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 11.5px;
    color: var(--text-faint);
    margin-top: -4px;
}

.auth-rules .ok[b-bk0as8u2mp] { color: var(--text-dim); }

.sr-only[b-bk0as8u2mp] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* /Components/Pages/Schedule.razor.rz.scp.css */
.page-header[b-7htuy869le] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.page-title[b-7htuy869le] { font-size: 17px; font-weight: 700; }

.page-sub[b-7htuy869le] {
    font-size: 12px;
    color: var(--text-dim);
    margin-top: 2px;
    max-width: 62ch;
}

.header-actions[b-7htuy869le] { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.nav-arrows[b-7htuy869le] { display: flex; gap: 4px; }

/* ---------- Filters ---------- */

.filter-sel[b-7htuy869le] {
    padding: 6px 10px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    font-family: inherit;
    font-size: 11.5px;
    outline: none;
    cursor: pointer;
}

.filter-sel:focus[b-7htuy869le] { border-color: var(--accent-glow); }

/* An active filter is lit: the numbers above are answering a narrower question
   than the page title suggests, and that must be visible at a glance. */
.sel-on[b-7htuy869le] {
    border-color: var(--accent-glow);
    background: var(--accent-glow-soft);
    color: var(--text-main);
    font-weight: 600;
}

/* ---------- Range totals ---------- */

/* Beside the range's name, on the left, because it belongs to it: these numbers
   are what the visible Day/Week/Month is worth, and they change with it. */
.head-left[b-7htuy869le] {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
}

.range-stats[b-7htuy869le] {
    display: flex;
    align-items: stretch;
    gap: 0;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    overflow: hidden;
}

.rstat[b-7htuy869le] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    padding: 6px 14px;
}

/* A hairline between figures rather than gaps: they are one readout, not three
   separate widgets. */
.rstat + .rstat[b-7htuy869le] { border-left: 1px solid var(--glass-border); }

.rstat-val[b-7htuy869le] { font-size: 15px; font-weight: 700; color: var(--text-main); line-height: 1.1; }
.rstat-money[b-7htuy869le] { color: #F2BE72; }

/* Cancelled is red and last — it is a footnote to the two numbers that matter,
   and it only appears when there is one. */
.rstat-off[b-7htuy869le] { color: #E88A84; }

.rstat-lbl[b-7htuy869le] {
    font-size: 8.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-faint);
}

/* ---------- View switch ---------- */

.view-switch[b-7htuy869le] {
    display: flex;
    gap: 2px;
    padding: 3px;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
}

.vt[b-7htuy869le] {
    padding: 5px 12px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-faint);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: 0.2s;
}

.vt:hover[b-7htuy869le] { color: var(--text-main); }

.vt-on[b-7htuy869le] {
    color: var(--accent-text-on-fill);
    background: var(--accent-gradient);
    box-shadow: 0 0 12px var(--accent-glow-soft);
}

/* ---------- Hours ---------- */

.tabs[b-7htuy869le] {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    margin-bottom: 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--glass-border);
}

/* Glass, like every other surface in the panel. These were transparent with a
   transparent border, so an unselected tab was floating text and the row read
   as a list of words rather than as something to press. */
.tab[b-7htuy869le] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 13px;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-dim);
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    cursor: pointer;
    transition: background .2s, color .2s, border-color .2s, transform .2s, box-shadow .2s;
}

.tab:hover[b-7htuy869le] {
    background: var(--accent-glow-soft);
    color: var(--text-main);
    transform: translateY(-1px);
}

/* The selected one is RAISED, not merely tinted: lifted off the row with a
   glow, so which staff member is on screen is obvious without reading. */
.tab-on[b-7htuy869le] {
    color: var(--text-main);
    font-weight: 600;
    background: var(--accent-glow-soft);
    border-color: var(--accent-glow);
    box-shadow: 0 0 14px var(--accent-glow-soft),
                inset 0 1px 0 rgba(255, 255, 255, 0.10);
}

.tab-on:hover[b-7htuy869le] { transform: none; }   /* already up */

/* A saffron dot marks the staff who deviate — the exception is what the owner
   is scanning for. */
.tab-dot[b-7htuy869le] {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #E9A13B;
    box-shadow: 0 0 6px rgba(233, 161, 59, 0.8);
}

.banner[b-7htuy869le] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 13px;
    margin-bottom: 14px;
    font-size: 12px;
    line-height: 1.65;
    color: var(--text-dim);
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
}

.banner strong[b-7htuy869le] { color: var(--text-main); font-weight: 600; }
.banner-info[b-7htuy869le] { background: var(--accent-glow-soft); }

/* Warn, not error: an override is a legitimate choice — it just has a
   consequence the owner must not misread as "adds to". */
.banner-warn[b-7htuy869le] {
    background: rgba(233, 161, 59, 0.09);
    border-color: rgba(233, 161, 59, 0.28);
}

/* Says out loud that these rules repeat — the whole view is otherwise
   indistinguishable from editing one specific week. */
.rule-note[b-7htuy869le] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 9px 12px;
    margin-bottom: 12px;
    font-size: 11.5px;
    line-height: 1.6;
    color: var(--text-dim);
    background: var(--accent-glow-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
}

.rule-note strong[b-7htuy869le] { color: var(--text-main); font-weight: 600; }

/* A button, not an anchor: it switches view, it doesn't navigate. */
.linkish[b-7htuy869le] {
    padding: 0;
    font: inherit;
    color: var(--text-dim);
    background: none;
    border: none;
    text-decoration: underline;
    cursor: pointer;
}

.linkish:hover[b-7htuy869le] { color: var(--text-main); }

/* Says the grid below is borrowed from the salon, not this person's own — so
   hitting Save is understood as "give them their own", not "confirm". */
.inherit-note[b-7htuy869le] {
    padding: 8px 12px;
    margin-bottom: 10px;
    font-size: 11.5px;
    line-height: 1.6;
    color: var(--text-faint);
    background: var(--glass-bg-soft);
    border: 1px dashed var(--glass-border);
    border-radius: var(--radius-md);
}

/* 6px, not 4: each row now carries its own border, and at four the edges of
   two neighbours nearly touch and read as one double line. */
.days[b-7htuy869le] { display: flex; flex-direction: column; gap: 6px; }

/* Each day is a card, not a line of text. Seven transparent rows with
   transparent borders read as a wall of times with nothing separating them;
   giving each one an edge is what makes the week scannable. */
.day[b-7htuy869le] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 11px;
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    transition: background .15s, border-color .15s, box-shadow .15s;
}

/* An open day is LIT — a soft accent glow, the same language the schedule uses
   for "today" — and a closed one keeps the plain glass and recedes. The week
   reads at a glance without anyone parsing the times. */
.day-on[b-7htuy869le] {
    background: var(--accent-glow-soft);
    border-color: var(--accent-glow);
    box-shadow: 0 0 12px var(--accent-glow-soft),
                inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* Closed days are quieter still: the times inside are disabled anyway, and
   fading the row says so before the reader looks at them. */
.day:not(.day-on) .day-name[b-7htuy869le] { color: var(--text-dim); }

.day-name[b-7htuy869le] {
    display: flex;
    align-items: baseline;
    gap: 9px;
    min-width: 13rem;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-main);
    cursor: pointer;
}

.day-name input[b-7htuy869le] {
    width: 15px;
    height: 15px;
    align-self: center;
    accent-color: #4E86E0;
    cursor: pointer;
}

.dn[b-7htuy869le] { min-width: 5.2rem; }

/* Anchors the weekly rule to a real date the owner can recognise. */
.dn-next[b-7htuy869le] { font-size: 10px; }

.times[b-7htuy869le] { display: flex; align-items: center; gap: 7px; }

.len[b-7htuy869le] { font-size: 10.5px; margin-left: 2px; }

.time[b-7htuy869le] {
    width: auto;
    padding: 6px 9px;
    font-size: 12px;
    color-scheme: dark;
    /* Clock fields read left-to-right — 09:00, not 00:90. */
    direction: ltr;
}

.dash[b-7htuy869le] { font-size: 11px; }
.closed[b-7htuy869le] { font-size: 11.5px; }

.week-foot[b-7htuy869le] {
    display: flex;
    gap: 8px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--glass-border);
}

/* ---------- Time-off form ---------- */

.presets[b-7htuy869le] { display: flex; gap: 5px; flex-wrap: wrap; }

.pair[b-7htuy869le] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.preview[b-7htuy869le] {
    display: flex;
    align-items: baseline;
    gap: 6px;
    padding: 10px 13px;
    font-size: 12px;
    background: var(--accent-glow-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
}

.preview strong[b-7htuy869le] { color: var(--text-main); font-size: 14px; }

.actions[b-7htuy869le] { display: flex; gap: 2px; }
.danger-text[b-7htuy869le] { color: var(--text-error); }
.danger-text:hover[b-7htuy869le] { background: rgba(180, 55, 47, 0.14); border-color: transparent; }

/* ---------- Booking dialog ---------- */

.bk-head[b-7htuy869le] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--glass-border);
}

.bk-day[b-7htuy869le] { font-size: 14px; font-weight: 700; }
.bk-hours[b-7htuy869le] { font-size: 12px; color: var(--text-dim); margin-top: 2px; }

.bk-facts[b-7htuy869le] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px 16px;
    margin: 14px 0 0;
}

.bk-wide[b-7htuy869le] { grid-column: 1 / -1; }

.bk-fact dt[b-7htuy869le] {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: .5px;
    margin-bottom: 3px;
}

.bk-fact dd[b-7htuy869le] { margin: 0; font-size: 12.5px; color: var(--text-main); }

/* Ties the dialog back to the block that was clicked. */
.svc-dot[b-7htuy869le] {
    display: inline-block;
    width: 9px;
    height: 9px;
    margin-right: 7px;
    border-radius: 50%;
    background: var(--svc);
    box-shadow: 0 0 6px var(--svc-dim);
}

.bk-tel[b-7htuy869le] { color: var(--text-dim); text-decoration: none; }
.bk-tel:hover[b-7htuy869le] { color: var(--text-main); text-decoration: underline; }

.bk-price[b-7htuy869le] { color: #F2BE72; font-weight: 700; }

/* The source, spelled out here rather than left as a glyph: the dialog has room
   for the word, and this is where the owner is deciding what to do about it. */
.src-tag[b-7htuy869le] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    border-radius: 999px;
    border: 1px solid;
    font-size: 11px;
    font-weight: 600;
}

.src-phone[b-7htuy869le] {
    color: #A5C8F0;
    background: rgba(120, 180, 255, 0.10);
    border-color: rgba(120, 180, 255, 0.30);
}

.src-online[b-7htuy869le] {
    color: #86EFAC;
    background: rgba(74, 222, 128, 0.10);
    border-color: rgba(74, 222, 128, 0.28);
}

.bk-notes[b-7htuy869le] {
    margin-top: 14px;
    padding: 10px 12px;
    border-radius: var(--radius-md);
    background: rgba(233, 161, 59, 0.09);
    border: 1px solid rgba(233, 161, 59, 0.28);
}

.bk-notes-label[b-7htuy869le] {
    font-size: 10px;
    font-weight: 700;
    color: #F2BE72;
    text-transform: uppercase;
    letter-spacing: .5px;
    margin-bottom: 4px;
}

.bk-notes p[b-7htuy869le] { font-size: 12.5px; line-height: 1.7; color: var(--text-dim); }

/* The confirmation says what actually happens — including the part we do NOT
   do, which is tell the customer. */
.bk-confirm[b-7htuy869le] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 14px;
    padding: 11px 12px;
    border-radius: var(--radius-md);
    background: rgba(180, 55, 47, 0.12);
    border: 1px solid rgba(248, 113, 113, 0.32);
}

.bk-confirm strong[b-7htuy869le] { font-size: 12.5px; color: #E88A84; }
.bk-confirm span[b-7htuy869le] { font-size: 11.5px; line-height: 1.6; color: var(--text-dim); }

/* Telling the customer. Separated by a rule from the warning above it: that
   part is about the appointment, this is a decision the owner is making — and
   it is the one thing in this dialog they can still change. */
.bk-tell[b-7htuy869le] {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 8px;
    padding-top: 9px;
    border-top: 1px solid rgba(248, 113, 113, 0.22);
    cursor: pointer;
}

/* Big enough to hit on a phone, where this dialog is often read. */
.bk-tell input[b-7htuy869le] {
    flex: none;
    width: 15px;
    height: 15px;
    margin-top: 1px;
    accent-color: #E88A84;
    cursor: pointer;
}

.bk-tell .num[b-7htuy869le] { color: var(--text-main); }

/* No number on file. Deliberately NOT styled as an error — nothing has gone
   wrong, but the owner has to leave knowing this customer needs a phone call. */
.bk-tell-none[b-7htuy869le] {
    margin-top: 8px;
    padding-top: 9px;
    border-top: 1px solid rgba(248, 113, 113, 0.22);
}

/* ---------- Responsive ---------- */

@media (max-width: 640px) {
    .bk-facts[b-7htuy869le] { grid-template-columns: 1fr; }
    .day[b-7htuy869le] { flex-direction: column; align-items: stretch; gap: 7px; }
    .pair[b-7htuy869le] { grid-template-columns: 1fr; }
}
/* /Components/Pages/Services.razor.rz.scp.css */
.page-header[b-q01bf7maxd] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

.page-title[b-q01bf7maxd] { font-size: 17px; font-weight: 700; }

.page-sub[b-q01bf7maxd] {
    font-size: 12px;
    color: var(--ink-dim);
    margin-top: 2px;
    max-width: 62ch;
}

/* The two numbers an owner actually compares down the column. */
.blocks[b-q01bf7maxd] { color: var(--ink) !important; font-weight: 700; }
.price[b-q01bf7maxd] { color: var(--saffron-soft) !important; font-weight: 700; }

.actions[b-q01bf7maxd] { display: flex; gap: 2px; }

.danger-text[b-q01bf7maxd] { color: #E88A84; }
.danger-text:hover[b-q01bf7maxd] { color: #FCA5A5; background: rgba(180, 55, 47, 0.14); border-color: transparent; }

.note[b-q01bf7maxd] {
    margin-top: 12px;
    padding: 9px 12px;
    font-size: 12px;
    color: var(--ink-muted);
    background: rgba(233, 161, 59, 0.08);
    border: 1px solid rgba(233, 161, 59, 0.25);
    border-radius: var(--r-sm);
}

.note a[b-q01bf7maxd] { color: var(--saffron-soft); text-decoration: underline; }

.pair[b-q01bf7maxd] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.hint[b-q01bf7maxd] { font-size: 10.5px; }

/* Live arithmetic: the owner sets two numbers, this shows the one the
   calendar will actually use. */
.preview[b-q01bf7maxd] {
    display: flex;
    align-items: baseline;
    gap: 5px;
    flex-wrap: wrap;
    padding: 9px 12px;
    font-size: 12px;
    background: rgba(78, 134, 224, 0.1);
    border: 1px solid rgba(78, 134, 224, 0.25);
    border-radius: var(--r-sm);
}

.preview strong[b-q01bf7maxd] { color: var(--ink); font-size: 13px; }

/* ---------- Colour picker ---------- */

.swatches[b-q01bf7maxd] { display: flex; gap: 8px; flex-wrap: wrap; }

/* The radio itself is hidden but still present and focusable — this has to stay
   a real radio group for the keyboard and for screen readers, and a div with
   click handlers would be neither. */
.swatch input[b-q01bf7maxd] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.swatch[b-q01bf7maxd] {
    position: relative;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    transition: transform .12s, border-color .12s;
}

.swatch:hover[b-q01bf7maxd] { transform: scale(1.1); }

.sw-dot[b-q01bf7maxd] {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--svc);
}

/* The ring, not a tick: a checkmark drawn over the colour hides the very thing
   being chosen. */
.sw-on[b-q01bf7maxd] { border-color: var(--svc); }
.sw-on .sw-dot[b-q01bf7maxd] { box-shadow: 0 0 10px var(--svc); }

/* Focus must be visible even on the unselected swatches — keyboard users need
   to see where they are before they commit. */
.swatch:focus-within[b-q01bf7maxd] { border-color: var(--ink); }

/* The real thing, in the preview line: what the day grid will actually draw. */
.chip-demo[b-q01bf7maxd] {
    padding: 2px 9px;
    border-radius: 5px;
    border-left: 3px solid var(--svc);
    background: var(--svc-dim);
    color: var(--svc-lit);
    font-size: 11.5px;
    font-weight: 600;
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------- Colour in the list ---------- */

.svc-name[b-q01bf7maxd] { display: inline-flex; align-items: center; gap: 8px; }

.svc-dot[b-q01bf7maxd] {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--svc);
    box-shadow: 0 0 6px var(--svc-dim);
}

.confirm[b-q01bf7maxd] { font-size: 12.5px; line-height: 1.7; color: var(--ink-muted); }
.confirm strong[b-q01bf7maxd] { color: var(--ink); }

@media (max-width: 560px) {
    .pair[b-q01bf7maxd] { grid-template-columns: 1fr; }
}
/* /Components/Pages/Settings.razor.rz.scp.css */
/* The business page: a long form on the left, the things you look AT
   (branding, the public page) on the right. */

.page-header[b-72ckuijlcu] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}

.page-title[b-72ckuijlcu] { font-size: 17px; font-weight: 700; }

.page-sub[b-72ckuijlcu] {
    font-size: 12px;
    color: var(--text-faint);
    margin-top: 3px;
}

/* One column, capped. The two-column grid that was here went with the Gallery,
   Branding and Public page cards on 2026-08-23 — with a single card the right
   half sat empty, which reads as content failing to load rather than as a short
   page. The cap keeps the inputs a readable width instead of stretching them
   across a wide monitor. */
.single-col[b-72ckuijlcu] {
    max-width: 760px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.card-body[b-72ckuijlcu] { display: flex; flex-direction: column; gap: 14px; }

.pair[b-72ckuijlcu] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.hint[b-72ckuijlcu] { font-size: 10.5px; }
.hint.err[b-72ckuijlcu] { color: var(--text-error); }

textarea.area[b-72ckuijlcu] { resize: vertical; min-height: 84px; line-height: 1.6; }

/* The DID: shaped like an input so it reads as part of the form, styled dead
   so it doesn't invite a click that goes nowhere. */
.readonly[b-72ckuijlcu] {
    padding: 9px 11px;
    border: 1px dashed var(--glass-border);
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    color: var(--text-faint);
    font-size: 12.5px;
}

.row-actions[b-72ckuijlcu] { display: flex; gap: 8px; align-items: center; }

.note[b-72ckuijlcu] {
    font-size: 11.5px;
    line-height: 1.7;
    color: var(--text-faint);
}

.note a[b-72ckuijlcu] { color: var(--saffron-soft); text-decoration: underline; }

.danger-text[b-72ckuijlcu] { color: #E88A84; }
.danger-text:hover[b-72ckuijlcu] { color: #FCA5A5; background: rgba(180, 55, 47, 0.14); border-color: transparent; }

/* ---------- Branding ---------- */

.brand-row[b-72ckuijlcu] {
    display: flex;
    gap: 12px;
    align-items: flex-start;
}

.brand-prev[b-72ckuijlcu] {
    flex: none;
    display: grid;
    place-items: center;
    overflow: hidden;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
}

.logo-prev[b-72ckuijlcu] { width: 62px; height: 62px; }
.banner-prev[b-72ckuijlcu] { width: 108px; height: 62px; }

.brand-prev img[b-72ckuijlcu] { width: 100%; height: 100%; object-fit: cover; display: block; }

.brand-prev .ph[b-72ckuijlcu] {
    font-size: 9.5px;
    color: var(--text-faint);
    text-align: center;
    padding: 4px;
}

.brand-ctl[b-72ckuijlcu] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    min-width: 0;
}

/* ---------- Uploader ---------- */

/* The real <input type=file> is hidden and the label is the button: the native
   control can't be styled and reads "Choose File / no file chosen" in English
   regardless of the page. The label keeps the click target and the keyboard
   path, because the input is still there. */
.uploader[b-72ckuijlcu] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border: 1px dashed var(--glass-border);
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color .15s, color .15s;
}

.uploader:hover[b-72ckuijlcu] { border-color: var(--accent-glow); color: var(--text-main); }
.uploader-sm[b-72ckuijlcu] { padding: 5px 10px; font-size: 11px; }

.uploader[b-72ckuijlcu]  input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

/* ---------- Gallery ---------- */

.gallery[b-72ckuijlcu] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: 10px;
}

.shot[b-72ckuijlcu] {
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--glass-bg-soft);
}

.shot img[b-72ckuijlcu] {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    display: block;
}

.shot figcaption[b-72ckuijlcu] {
    display: flex;
    gap: 4px;
    align-items: center;
    padding: 6px;
}

.input-sm[b-72ckuijlcu] {
    padding: 5px 8px;
    font-size: 11px;
    min-width: 0;
    flex: 1;
}

/* ---------- Public page ---------- */

.slug-row[b-72ckuijlcu] {
    display: flex;
    align-items: center;
    gap: 0;
}

.slug-pre[b-72ckuijlcu] {
    font-size: 11px;
    padding: 9px 6px 9px 0;
    white-space: nowrap;
}

.themes[b-72ckuijlcu] { display: flex; gap: 8px; flex-wrap: wrap; }

/* Each swatch carries its own data-theme, so --accent-gradient inside it is
   THAT theme's accent — the preview is the palette itself, not a copy of it
   that can drift. */
.swatch[b-72ckuijlcu] {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 7px 11px;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color .15s, color .15s;
}

.swatch:hover[b-72ckuijlcu] { color: var(--text-main); }

.sw-dot[b-72ckuijlcu] {
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: var(--accent-gradient);
    box-shadow: 0 0 0 1px var(--glass-border);
    flex: none;
}

.sw-on[b-72ckuijlcu] {
    border-color: var(--accent-glow);
    color: var(--text-main);
    box-shadow: 0 0 0 1px var(--accent-glow-soft);
}

/* ---------- Publish gate ---------- */

.gate[b-72ckuijlcu] {
    border: 1px solid rgba(251, 191, 36, 0.32);
    background: rgba(251, 191, 36, 0.10);
    border-radius: var(--radius-md);
    padding: 10px 12px;
}

.gate-title[b-72ckuijlcu] {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--warn);
    margin-bottom: 5px;
}

.gate-list[b-72ckuijlcu] {
    margin: 0;
    padding-left: 16px;
    font-size: 11.5px;
    line-height: 1.75;
    color: var(--text-faint);
}

/* The 1100px rule that collapsed .two-col went with the grid itself —
   .single-col is already one column at every width. */

@media (max-width: 700px) {
    .pair[b-72ckuijlcu] { grid-template-columns: 1fr; }
}
/* /Components/Pages/Staff.razor.rz.scp.css */
.page-header[b-dwzyyfvsmh] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

.page-title[b-dwzyyfvsmh] { font-size: 17px; font-weight: 700; }

.page-sub[b-dwzyyfvsmh] {
    font-size: 12px;
    color: var(--ink-dim);
    margin-top: 2px;
    max-width: 62ch;
}

.actions[b-dwzyyfvsmh] { display: flex; gap: 2px; align-items: center; }
.actions a[b-dwzyyfvsmh] { text-decoration: none; }

.danger-text[b-dwzyyfvsmh] { color: #E88A84; }
.danger-text:hover[b-dwzyyfvsmh] { color: #FCA5A5; background: rgba(180, 55, 47, 0.14); border-color: transparent; }

/* Service picker: rows, not a dense grid — each line carries the duration and
   price so the choice is made with the numbers visible. */
.checks[b-dwzyyfvsmh] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    max-height: 300px;
    overflow-y: auto;
    padding: 5px;
    background: var(--sunken);
    border: 1px solid var(--glass-border);
    border-radius: var(--r-sm);
}

.check[b-dwzyyfvsmh] {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 8px;
    border-radius: 6px;
    cursor: pointer;
}

.check-row[b-dwzyyfvsmh] { border-radius: 6px; transition: background 0.12s; }

/* A ticked service opens its own price/duration fields, so the row grows. */
.check-on[b-dwzyyfvsmh] { background: var(--glow-soft); }
.check-row:not(.check-on):hover[b-dwzyyfvsmh] { background: var(--glow-soft); }

/* The overrides sit under their service, indented to the checkbox's label. */
.ovr[b-dwzyyfvsmh] {
    display: flex;
    gap: 8px;
    padding: 0 8px 8px 32px;
}

.ovr-f[b-dwzyyfvsmh] { display: flex; align-items: center; gap: 4px; }

.ovr-l[b-dwzyyfvsmh] { font-size: 11px; color: var(--ink-faint); }

.ovr-i[b-dwzyyfvsmh] {
    width: 74px;
    padding: 5px 7px;
    font-size: 12px;
}

/* The placeholder carries the inherited value, so an empty field reads as
   "same as the service" rather than "unset". */
.ovr-i[b-dwzyyfvsmh]::placeholder { color: var(--ink-faint); opacity: 0.7; }

.check input[b-dwzyyfvsmh] {
    width: 15px;
    height: 15px;
    accent-color: var(--accent);
    flex-shrink: 0;
    cursor: pointer;
}

.check-name[b-dwzyyfvsmh] { font-size: 12.5px; font-weight: 500; color: var(--ink); }

.check-meta[b-dwzyyfvsmh] {
    margin-left: auto;
    font-size: 10.5px;
}

.toggle[b-dwzyyfvsmh] {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 10px 12px;
    background: var(--sunken);
    border: 1px solid var(--glass-border);
    border-radius: var(--r-sm);
    cursor: pointer;
}

.toggle input[b-dwzyyfvsmh] {
    width: 15px;
    height: 15px;
    margin-top: 2px;
    accent-color: var(--accent);
    flex-shrink: 0;
    cursor: pointer;
}

.toggle > span[b-dwzyyfvsmh] { display: flex; flex-direction: column; gap: 2px; }

.toggle-title[b-dwzyyfvsmh] { font-size: 12.5px; color: var(--ink); }
.toggle-hint[b-dwzyyfvsmh] { font-size: 10.5px; }

.hint[b-dwzyyfvsmh] { font-size: 11.5px; }
.hint a[b-dwzyyfvsmh] { color: var(--accent2); text-decoration: underline; }

.confirm[b-dwzyyfvsmh] { font-size: 12.5px; line-height: 1.7; color: var(--ink-muted); }
.confirm strong[b-dwzyyfvsmh] { color: var(--ink); }
/* /Components/Pages/Support.razor.rz.scp.css */
/* Contact us.
 *
 * Every colour is a theme token or one of the theme-independent --svc-* hues.
 * The panel runs three themes; a literal hex looks right in one and wrong in
 * the other two.
 */

.sup-grid[b-6xn2qfcu4z] {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

/* The side column stops being a side column before it gets too narrow to read
   a phone number in. */
@media (max-width: 900px) {
    .sup-grid[b-6xn2qfcu4z] { grid-template-columns: minmax(0, 1fr); }
}

.sup-side[b-6xn2qfcu4z] {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* A tinted top edge per card, so the three purposes read apart at a glance
   rather than as one grey stack. Layered OVER the glass, never replacing it. */
.sup-card[b-6xn2qfcu4z] {
    position: relative;
    overflow: hidden;
}

.sup-card[b-6xn2qfcu4z]::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 2px;
    opacity: .8;
}

.sup-write[b-6xn2qfcu4z]::before {
    background: linear-gradient(90deg, var(--svc-lajvard), var(--svc-turquoise));
}

.sup-call[b-6xn2qfcu4z]::before { background: var(--svc-pistachio); }
.sup-mail[b-6xn2qfcu4z]::before { background: var(--svc-saffron); }
.sup-tips[b-6xn2qfcu4z]::before { background: var(--svc-plum); }

/* ---------- The form ---------- */

.field[b-6xn2qfcu4z] { margin-bottom: 16px; }

.field .label[b-6xn2qfcu4z] {
    display: block;
    margin-bottom: 7px;
}

.area[b-6xn2qfcu4z] {
    resize: vertical;
    min-height: 130px;
    font-family: inherit;
    line-height: 1.6;
}

.hint[b-6xn2qfcu4z] {
    display: block;
    margin-top: 6px;
    font-size: 11px;
    line-height: 1.5;
}

.topic-row[b-6xn2qfcu4z] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.topic[b-6xn2qfcu4z] {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    border-radius: 999px;
    padding: 8px 14px;
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
    transition: border-color .12s ease, background .12s ease, color .12s ease;
}

.topic:hover[b-6xn2qfcu4z] {
    border-color: var(--text-dim);
    color: var(--text);
}

/* The chosen topic changes weight and background, not just colour — colour
   alone is invisible to about one man in twelve. */
.topic.on[b-6xn2qfcu4z] {
    background: color-mix(in srgb, var(--svc-lajvard) 22%, transparent);
    border-color: var(--svc-lajvard);
    color: var(--text);
    font-weight: 600;
}

.topic-icon[b-6xn2qfcu4z] { font-size: 13px; }

@media (prefers-reduced-motion: reduce) {
    .topic[b-6xn2qfcu4z] { transition: none; }
}

.sup-reply-to[b-6xn2qfcu4z] {
    font-size: 11.5px;
    /* Sits beside the button rather than under it: it answers "where does the
       answer go?", which is asked at the moment of pressing send. */
    align-self: center;
}

/* ---------- Sent ---------- */

.sup-done[b-6xn2qfcu4z] {
    text-align: center;
    padding: 26px 10px 18px;
}

.sup-tick[b-6xn2qfcu4z] {
    width: 46px;
    height: 46px;
    margin: 0 auto 14px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 22px;
    font-weight: 700;
    color: #0d1b16;
    background: var(--svc-pistachio);
    box-shadow: 0 4px 18px color-mix(in srgb, var(--svc-pistachio) 45%, transparent);
}

.sup-done-title[b-6xn2qfcu4z] {
    font-size: 16px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 8px;
}

.sup-done-note[b-6xn2qfcu4z] {
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-dim);
    margin: 0 auto 18px;
    max-width: 380px;
}

.sup-done-note strong[b-6xn2qfcu4z] {
    color: var(--text);
    word-break: break-word;
}

/* ---------- Side cards ---------- */

.sup-side-label[b-6xn2qfcu4z] {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--text-faint);
    margin-bottom: 9px;
}

/* Big, because on a phone this is a tap target and on a desktop it is the thing
   being read aloud to someone dialling. */
.sup-phone[b-6xn2qfcu4z] {
    display: inline-block;
    font-size: 21px;
    font-weight: 700;
    color: var(--svc-pistachio-lit);
    text-decoration: none;
    font-variant-numeric: tabular-nums;
    letter-spacing: .01em;
}

.sup-phone:hover[b-6xn2qfcu4z] { text-decoration: underline; }

.sup-hours[b-6xn2qfcu4z] {
    margin-top: 6px;
    font-size: 11.5px;
    color: var(--text-dim);
}

.sup-email[b-6xn2qfcu4z] {
    font-size: 14px;
    font-weight: 600;
    color: var(--svc-saffron-lit);
    text-decoration: none;
    word-break: break-word;
}

.sup-email:hover[b-6xn2qfcu4z] { text-decoration: underline; }

.sup-list[b-6xn2qfcu4z] {
    margin: 0;
    padding-inline-start: 17px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    font-size: 12px;
    line-height: 1.6;
    color: var(--text-dim);
}

.sup-list a[b-6xn2qfcu4z] { color: var(--text); }
/* /Components/Pages/VoiceRequests.razor.rz.scp.css */
/* The waiting list.
   Each card is a person who rang and hasn't been answered. The colour carries
   the only question the page exists to answer — who to deal with first — so it
   encodes urgency, never decoration. */

.req-list[b-4nel69jven] {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px;
}

.req[b-4nel69jven] {
    position: relative;
    display: flex;
    gap: 0;
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    background: var(--glass-bg-soft);
    overflow: hidden;
    transition: border-color .15s ease, background .15s ease;
}

.req:hover[b-4nel69jven] {
    background: var(--glass-bg);
}

/* A colour bar rather than a tinted card: the tint has to stay light enough for
   Persian text to read at 13px, and a 4px rail carries the state just as well
   from across a salon counter. */
.req-rail[b-4nel69jven] {
    flex: 0 0 4px;
    align-self: stretch;
}

.req.is-review .req-rail[b-4nel69jven] { background: var(--color-danger, #B4372F); }
.req.is-stale  .req-rail[b-4nel69jven] { background: var(--color-warning, #E9A13B); }
.req.is-fresh  .req-rail[b-4nel69jven] { background: var(--color-success, #4ADE80); }

/* The one the receptionist couldn't understand gets a tint as well as a rail —
   it is the only state where the owner must open the call before deciding. */
.req.is-review[b-4nel69jven] {
    background: rgba(180, 55, 47, 0.08);
    border-color: rgba(255, 138, 138, 0.28);
}

.req-main[b-4nel69jven] {
    flex: 1 1 auto;
    min-width: 0;
    padding: 9px 12px;
}

/* Name, facts and waiting time all on ONE line. They used to be two rows, which
   made every card twice as tall for four short words and pushed the next caller
   off the screen — on a queue whose whole job is "who's waiting?", fewer visible
   callers is the one thing that cannot be traded away. */
.req-top[b-4nel69jven] {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    min-width: 0;
}

.req-name[b-4nel69jven] {
    font-weight: 700;
    font-size: 13.5px;
    margin-right: 2px;
}

/* Pushed to the far end of the line, so waiting time reads as a column even
   though everything before it varies in width. */
.req-age[b-4nel69jven] {
    margin-left: auto;
    font-size: 11.5px;
    color: var(--text-faint);
    white-space: nowrap;
    padding-left: 8px;
}

/* Over a day unanswered. Stated in the text colour too, not only the rail —
   colour alone is invisible to a colour-blind owner. */
.req-age.is-stale[b-4nel69jven] {
    color: #F5C97B;
    font-weight: 600;
}

.fact[b-4nel69jven] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11.5px;
    padding: 2px 8px;
    border-radius: 999px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text-dim);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Each fact gets its own hue so the eye can find "which service?" without
   reading the row left to right — the old page was one blue and had to be read
   word by word. */
.fact.is-service[b-4nel69jven] {
    color: #9CC4FF;
    border-color: rgba(78, 134, 224, 0.34);
    background: rgba(35, 80, 155, 0.16);
}

.fact.is-staff[b-4nel69jven] {
    color: #C9B6F5;
    border-color: rgba(167, 139, 250, 0.32);
    background: rgba(124, 92, 220, 0.14);
}

.fact.is-when[b-4nel69jven] {
    color: #86EFAC;
    border-color: rgba(74, 222, 128, 0.3);
    background: rgba(74, 222, 128, 0.12);
}

.fact.is-phone[b-4nel69jven] {
    color: #F5C97B;
    border-color: rgba(233, 161, 59, 0.34);
    background: rgba(233, 161, 59, 0.13);
    text-decoration: none;
}

.fact.is-phone:hover[b-4nel69jven] {
    background: rgba(233, 161, 59, 0.24);
}

/* Something the receptionist heard but couldn't match. Saffron, and it must
   never look like a settled fact — it is the thing to check. */
.fact.is-unsure[b-4nel69jven] {
    color: #F5C97B;
    border-color: rgba(233, 161, 59, 0.4);
    background: rgba(233, 161, 59, 0.13);
    border-style: dashed;
}

/* The caller's own words. Never hidden behind a click: an allergy or "bringing
   my daughter" changes how the booking is made. */
.req-note[b-4nel69jven] {
    margin-top: 7px;
    padding: 6px 9px;
    border-left: 2px solid var(--glass-border);
    background: var(--glass-bg-soft);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-dim);
}

/* One row under the card, not a column beside it. A vertical stack of four
   buttons set the card's height on its own — the card was as tall as its
   actions rather than its content. */
.req-actions[b-4nel69jven] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}

.req-actions .btn[b-4nel69jven] {
    padding: 4px 11px;
    font-size: 11.5px;
}

/* Four actions, four meanings, four colours. They were all the same blue, so
   "Book it" and "Decline" looked equally likely — on a screen where one makes
   money and the other turns a customer away. */
.btn-book[b-4nel69jven] {
    background: rgba(74, 222, 128, 0.18);
    border-color: rgba(74, 222, 128, 0.38);
    color: #86EFAC;
}

.btn-book:hover[b-4nel69jven] {
    background: rgba(74, 222, 128, 0.3);
}

.btn-listen[b-4nel69jven] {
    background: rgba(35, 80, 155, 0.22);
    border-color: rgba(78, 134, 224, 0.34);
    color: #9CC4FF;
}

.btn-listen:hover[b-4nel69jven] {
    background: rgba(35, 80, 155, 0.36);
}

.btn-done[b-4nel69jven] {
    background: rgba(233, 161, 59, 0.16);
    border-color: rgba(233, 161, 59, 0.34);
    color: #F5C97B;
}

.btn-done:hover[b-4nel69jven] {
    background: rgba(233, 161, 59, 0.28);
}

/* Declining is the one irreversible-feeling action here, so it stays quiet
   until reached for — loud red on a list of four buttons invites a mis-click. */
.btn-drop[b-4nel69jven] {
    background: transparent;
    border-color: var(--glass-border);
    color: var(--text-faint);
}

.btn-drop:hover[b-4nel69jven] {
    background: rgba(180, 55, 47, 0.18);
    border-color: rgba(255, 138, 138, 0.4);
    color: #FFB4B4;
}

.btn-call[b-4nel69jven] {
    background: rgba(233, 161, 59, 0.2);
    border-color: rgba(233, 161, 59, 0.4);
    color: #F5C97B;
    text-decoration: none;
}

.btn-call:hover[b-4nel69jven] {
    background: rgba(233, 161, 59, 0.32);
}

/* ---- Free times in the booking dialog ----
   The times that are genuinely open, so the owner picks one instead of retyping
   what the caller said and discovering at Confirm that it was sold an hour ago. */

.slot-grid[b-4nel69jven] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 4px;
    /* Cap the height: a quiet Tuesday can return forty starts, and a wall of
       them pushes the Confirm button off the dialog. */
    max-height: 168px;
    overflow-y: auto;
    padding: 2px;
}

.slot[b-4nel69jven] {
    appearance: none;
    border: 1px solid rgba(74, 222, 128, 0.3);
    background: rgba(74, 222, 128, 0.12);
    color: #86EFAC;
    border-radius: var(--radius-sm);
    padding: 6px 11px;
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
    white-space: nowrap;
    transition: background .12s ease, border-color .12s ease;
}

.slot:hover[b-4nel69jven] {
    background: rgba(74, 222, 128, 0.24);
}

.slot.is-on[b-4nel69jven] {
    background: rgba(74, 222, 128, 0.38);
    border-color: rgba(74, 222, 128, 0.75);
    color: #E9FFF1;
    font-weight: 700;
}

.slot-hint[b-4nel69jven] {
    font-size: 12.5px;
    line-height: 1.5;
    padding: 8px 0 2px;
}

/* A fully booked day is a normal answer, not a fault — saffron, never red. */
.slot-hint.is-none[b-4nel69jven] {
    color: #F5C97B;
}

/* The receptionist's own reading of the call, above the transcript. */
.detail[b-4nel69jven] {
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 8px 14px;
    margin: 0 0 6px;
}

.detail dt[b-4nel69jven] {
    color: var(--text-faint);
    font-size: 11.5px;
}

.detail dd[b-4nel69jven] {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.5;
}

.sec-title[b-4nel69jven] {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-faint);
    margin-bottom: 10px;
    font-weight: 700;
}

/* ---- The "what was said" drawer ----
   Same shape as the Calls page's drawer, redefined here because scoped CSS does
   not cross components. The stacking-context fix lives in app.css and is shared
   via Calls.razor.js. */

.drawer-scrim[b-4nel69jven] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 200;
}

.drawer[b-4nel69jven] {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(620px, 96vw);
    /* The page gradient under the theme's own glass. --surface does not exist in
       this theme; a hard-coded colour here would ignore the gold and lilac
       themes and leave the panel translucent. */
    background: var(--bg-gradient);
    border-left: 1px solid var(--glass-border);
    z-index: 201;
    display: flex;
    flex-direction: column;
    box-shadow: -12px 0 40px rgba(0, 0, 0, 0.4);
}

.drawer-head[b-4nel69jven] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding: 16px 18px;
    border-bottom: 1px solid var(--glass-border);
    flex: 0 0 auto;
}

.drawer-title[b-4nel69jven] {
    font-weight: 700;
    font-size: 15px;
}

.drawer-x[b-4nel69jven] {
    appearance: none;
    border: none;
    background: transparent;
    color: var(--text-dim);
    font-size: 16px;
    cursor: pointer;
    padding: 4px;
}

.drawer-x:hover[b-4nel69jven] {
    color: var(--text-main);
}

/* min-height:0 is what actually lets this scroll. A flex child defaults to
   min-height:auto, so it refuses to shrink below its content and a long
   transcript pushes the drawer instead of scrolling inside it. */
.drawer-body[b-4nel69jven] {
    padding: 18px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

/* The decisions stay on screen while the conversation is being read — that is
   the moment the owner makes up their mind. */
.drawer-foot[b-4nel69jven] {
    display: flex;
    gap: 8px;
    padding: 12px 18px;
    border-top: 1px solid var(--glass-border);
    flex: 0 0 auto;
}

/* Where a player would sit. The voice platform has no recording endpoint, and a
   silent empty player reads as broken — so the absence is stated instead. */
.no-audio[b-4nel69jven] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    margin-bottom: 16px;
    border: 1px dashed var(--glass-border);
    border-radius: var(--radius-sm);
    font-size: 12px;
    line-height: 1.5;
}

.turns[b-4nel69jven] {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.turn[b-4nel69jven] {
    border-radius: 10px;
    padding: 9px 12px;
    max-width: 88%;
    border: 1px solid var(--glass-border);
}

.turn-who[b-4nel69jven] {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-bottom: 3px;
    font-weight: 700;
}

.turn-text[b-4nel69jven] {
    font-size: 13px;
    line-height: 1.55;
    white-space: pre-wrap;
}

/* The receptionist is the house voice: lajvard, the brand blue. */
.t-agent[b-4nel69jven] {
    align-self: flex-start;
    background: rgba(35, 80, 155, 0.22);
    border-color: rgba(78, 134, 224, 0.28);
}

/* The caller gets the loudest colour on the page — "what did the customer
   actually say" is the one thing being scanned for. */
.t-caller[b-4nel69jven] {
    align-self: flex-end;
    background: rgba(74, 222, 128, 0.16);
    border-color: rgba(74, 222, 128, 0.3);
}
/* /Components/Shared/AccountAlerts.razor.rz.scp.css */
/* The account warning bar.
 *
 * Sits above the page content, inside .content, so it scrolls away rather than
 * eating vertical space on every screen of a long page — an owner who has read
 * it once should not have it pinned over their calendar all day.
 *
 * Colours are theme tokens plus colour-mix, never literals: the panel runs three
 * themes and a hard-coded red is right in one and muddy in the others.
 */

.acct-alert[b-bvslkf0nrw] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 14px;
    margin-bottom: 16px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    font-size: 13px;
    line-height: 1.45;
}

.acct-icon[b-bvslkf0nrw] {
    font-size: 16px;
    flex: none;
    line-height: 1;
}

.acct-text[b-bvslkf0nrw] {
    flex: 1 1 auto;
    min-width: 0;
}

.acct-text strong[b-bvslkf0nrw] {
    /* Inline, not a block: on a narrow screen the sentence should wrap as one
       paragraph rather than leaving a lone bold line above a stray clause. */
    margin-right: 5px;
}

.acct-alert .btn[b-bvslkf0nrw] {
    flex: none;
    white-space: nowrap;
}

/* ---- Tones ----
 *
 * Explicit rgba, matching .alert-error / .alert-warn in app.css rather than
 * inventing tokens. There is NO --danger in this theme (verified) — the palette
 * defines pomegranate #B4372F and saffron #E9A13B, and the alert classes tint
 * from those literals. A var() typo here would fall through to an untinted bar
 * that reads as ordinary content, which on the "your line has stopped" banner is
 * the one failure that matters.
 *
 * --glass-bg-soft and --glass-border DO exist (theme.css) and vary per theme, so
 * the base surface still follows blue/gold/lilac.
 */

.acct-alert.crit[b-bvslkf0nrw] {
    color: var(--text-error);
    border-color: rgba(255, 138, 138, 0.42);
    background: rgba(180, 55, 47, 0.17);
}

.acct-alert.warn[b-bvslkf0nrw] {
    color: #F5C97B;
    border-color: rgba(233, 161, 59, 0.36);
    background: rgba(233, 161, 59, 0.13);
}

.acct-alert.info[b-bvslkf0nrw] {
    border-color: rgba(120, 180, 255, 0.32);
    background: rgba(35, 80, 155, 0.14);
}

@media (max-width: 620px) {
    .acct-alert[b-bvslkf0nrw] {
        /* The action wraps to its own line rather than squeezing the sentence
           into a two-word-per-line column. */
        flex-wrap: wrap;
    }

    .acct-text[b-bvslkf0nrw] { flex: 1 1 100%; }
    .acct-alert .btn[b-bvslkf0nrw] { margin-left: 28px; }
}
/* /Components/Shared/DayGrid.razor.rz.scp.css */
/* The day grid's own styles, beside the component that draws them.

   The service palette (.sw-*) stays in app.css: it is shared with the week, the
   month, the dialog and the Services page, and CSS isolation would give each of
   them a private copy free to drift.
*/

/* ---------- Day: hours down, staff across ---------- */

/* The grid scrolls inside its own box rather than the page: the hour gutter and
   the column heads have to stay put while the day moves under them. */
.daygrid-wrap[b-dc3am9uccp] {
    overflow: auto;
    max-height: calc(100vh - 210px);
    padding: 1px;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}

/* One row per half hour, one column per staff member, plus the time gutter.
   --cols and --rows come from the component: the C# decides how many people are
   in and how long the day is, the CSS only decides how big a half hour looks. */
.daygrid[b-dc3am9uccp] {
    display: grid;
    grid-template-columns: 52px repeat(var(--cols), minmax(112px, 1fr));
    grid-template-rows: auto repeat(var(--rows), 26px);
    position: relative;
    min-width: fit-content;
}

/* Heads and gutter stay visible while the day scrolls under them — on a long
   day the owner would otherwise lose track of both whose column this is and
   what time they're looking at. */
.dg-head[b-dc3am9uccp], .dg-corner[b-dc3am9uccp] {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--glass-bg);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--glass-border);
}

.dg-corner[b-dc3am9uccp] { left: 0; z-index: 4; grid-row: 1; grid-column: 1; }

.dg-head[b-dc3am9uccp] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 7px 9px;
    border-left: 1px solid var(--glass-border);
}

.dg-staff[b-dc3am9uccp] { font-size: 12px; font-weight: 700; color: var(--text-main); }
.dg-load[b-dc3am9uccp] { font-size: 9.5px; font-weight: 600; color: #F2BE72; }

.dg-time[b-dc3am9uccp] {
    position: sticky;
    left: 0;
    z-index: 2;
    grid-column: 1;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding-right: 7px;
    /* The label sits on the line it names, not in the middle of the slot below
       it — a "10:00" floating between 10:00 and 10:30 belongs to neither. */
    transform: translateY(-50%);
    font-size: 9.5px;
    color: var(--text-faint);
    background: var(--glass-bg);
    pointer-events: none;
}

.dg-time-hr[b-dc3am9uccp] { color: var(--text-dim); font-weight: 600; }

/* The background cells: they are the grid lines, and the surface free time is
   read off. The hour line is brighter than the half — without the difference a
   long day is an undifferentiated ladder. */
.dg-cell[b-dc3am9uccp] { border-top: 1px solid rgba(255, 255, 255, 0.04); border-left: 1px solid var(--glass-border); }
.dg-cell-hr[b-dc3am9uccp] { border-top-color: rgba(255, 255, 255, 0.10); }

/* Outside this person's working hours. Hatched rather than merely darker: "not
   in" and "free" must not be a matter of guessing at a shade. */
.dg-shut[b-dc3am9uccp] {
    background: repeating-linear-gradient(
        45deg,
        transparent,
        transparent 5px,
        rgba(255, 255, 255, 0.028) 5px,
        rgba(255, 255, 255, 0.028) 10px
    );
}

/* ---------- An appointment on the day grid ---------- */

.dg-bk[b-dc3am9uccp] {
    /* --lane/--lanes split the column when blocks overlap; with one lane this is
       the whole width, which is the normal case. */
    width: calc((100% - 4px) / var(--lanes));
    margin-left: calc((100% - 4px) / var(--lanes) * var(--lane));
    z-index: 1;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 3px 6px;
    margin-top: 1px;
    margin-bottom: 1px;
    text-align: left;
    cursor: pointer;
    border: none;
    /* 4px, matching the week card: at three the strip is the only thing naming
       the service and it reads thin against a tall block. */
    border-left: 4px solid var(--svc-lit);
    border-radius: 5px;
    background: var(--svc-dim);
    font-family: inherit;

    /* The same glass and inner glow the week cards use, so a booking looks like
       the same object in both views rather than a flat swatch here and a lit
       card there. The glow is what gives the block depth against the grid. */
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: inset 3px 0 10px -3px var(--svc-lit),
                0 1px 3px rgba(0, 0, 0, 0.25);
    transition: filter .12s, box-shadow .12s, transform .12s;
}

.dg-bk:hover[b-dc3am9uccp] {
    filter: brightness(1.35);
    transform: translateX(1px);
    box-shadow: inset 3px 0 10px -3px var(--svc-lit),
                0 0 0 1px var(--svc), 0 4px 14px rgba(0, 0, 0, 0.35);
    z-index: 2;
}

.dgb-time[b-dc3am9uccp] { font-size: 9.5px; font-weight: 700; color: var(--svc-lit); line-height: 1.35; }

.dgb-name[b-dc3am9uccp] {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-main);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dgb-svc[b-dc3am9uccp] {
    font-size: 9px;
    color: var(--text-faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A 30-minute block is one row tall — there is room for the name and nothing
   else. The colour already carries the service. */
.dg-bk[b-dc3am9uccp] { line-height: 1.2; }

/* Status still shows through the service colour: a cancelled booking keeps its
   hue but stops pretending it's happening.

   The inner glow goes with it. Left on, a cancelled block sat there lit like a
   live one at reduced opacity, which is the one thing it must not look like. */
.dg-bk.chip-off[b-dc3am9uccp] {
    opacity: 0.45;
    background: transparent;
    border-left-style: dashed;
    box-shadow: none;
}
.dg-bk.chip-off .dgb-name[b-dc3am9uccp] { text-decoration: line-through; }

/* Not yet a commitment: amber and dashed, the same as every other pending in
   the panel — the week card included, so the two views agree. */
.dg-bk.chip-warn[b-dc3am9uccp] {
    border-left-color: #FBBF24;
    border-left-style: dashed;
}
.dg-bk.chip-warn .dgb-time[b-dc3am9uccp] { color: #FDE68A; }

/* ---------- Now ---------- */

/* Sits inside its row at the exact minute — --frac is how far through the half
   hour the clock is. */
.dg-now[b-dc3am9uccp] {
    position: relative;
    z-index: 3;
    pointer-events: none;
    align-self: start;
    margin-top: calc(26px * var(--frac));
    height: 0;
    border-top: 1px solid #E9A13B;
    box-shadow: 0 0 8px rgba(233, 161, 59, 0.7);
}

.dg-now[b-dc3am9uccp]::before {
    content: "";
    position: absolute;
    left: -3px;
    top: -3px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #E9A13B;
}

/* ---------- Legend ---------- */

/* Without this the colours are just decoration — this is where they become a
   key the owner can read the grid with. */
.dg-legend[b-dc3am9uccp] {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding: 8px 12px;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
}

.lg-item[b-dc3am9uccp] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    color: var(--text-dim);
}

.lg-dot[b-dc3am9uccp] {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--svc);
    box-shadow: 0 0 6px var(--svc-dim);
}


/* The day grid keeps its shape on a phone and scrolls sideways instead of
   folding: a time × staff grid with the staff axis removed is a list, which is
   the thing this view exists not to be. Columns just get narrower first. */
@media (max-width: 700px) {
    .daygrid[b-dc3am9uccp] { grid-template-columns: 42px repeat(var(--cols), minmax(96px, 1fr)); }
    .daygrid-wrap[b-dc3am9uccp] { max-height: calc(100vh - 240px); }
    .dgb-svc[b-dc3am9uccp] { display: none; }
}
/* /Components/Shared/HelpAssistantPanel.razor.rz.scp.css */
/* Help assistant: a floating button and the panel it opens.

   Every colour here is a theme token. The panel runs three themes (blue, gold,
   lilac) and a literal hex would look correct in one and wrong in the other
   two — the same trap that made the Calls drawer paint a hard navy over a gold
   theme. Tints layer over --glass-bg-soft rather than replacing it. */

/* ── The button ─────────────────────────────────────────────────────── */

/* ---- The trigger, sitting IN the topbar ----

   Positioned rather than placed. The panel this opens has to live outside
   `.main` (a stacking context that would paint it under the sidebar), so the
   component stays where it is and only the button is put into the bar —
   splitting the two would mean sharing open/close state across that boundary
   for no gain.

   Matched to .topbar's own geometry: fixed, right-aligned, and centred within
   --nav-h. If the bar's height changes, this follows it, because both read the
   same variable. */
.help-trigger[b-dvotbilit1] {
    position: fixed;
    top: 0;
    inset-inline-end: 20px;      /* .topbar's own padding */
    height: var(--nav-h, 60px);

    /* Above the topbar (90) and sidebar (100), like the old floating button —
       the panel and scrim go higher still. */
    z-index: 120;

    display: inline-flex;
    align-items: center;
    gap: 7px;

    padding: 0 12px;
    border: 1px solid transparent;
    background: none;
    color: var(--text-dim);
    font-size: 13px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: color .16s ease;
}

.help-trigger:hover[b-dvotbilit1] { color: var(--text-main); }

/* The icon carries the chrome, not the button: a full pill in the bar competes
   with the plan badge beside it, where a tinted glyph reads as one item. */
.help-trigger-icon[b-dvotbilit1] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 9px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    transition: background .16s ease, border-color .16s ease, transform .16s ease;
}

.help-trigger:hover .help-trigger-icon[b-dvotbilit1] {
    background: var(--glass-bg);
    transform: translateY(-1px);
}

/* Open is a STATE, so it is lit rather than merely hovered — the trigger is
   still on screen beside the panel and has to say which one it belongs to. */
.help-trigger.is-open[b-dvotbilit1] { color: var(--text-main); }

.help-trigger.is-open .help-trigger-icon[b-dvotbilit1] {
    border-color: var(--accent-glow, var(--glass-border));
    background: var(--accent-glow-soft, var(--glass-bg));
}

/* The word goes on narrow screens, the icon stays. A topbar that wraps is worse
   than an unlabelled button, and the icon is the part that is recognised. */
@media (max-width: 720px) {
    .help-trigger-text[b-dvotbilit1] { display: none; }
    .help-trigger[b-dvotbilit1] { padding: 0 8px; }
}

.help-fab:focus-visible[b-dvotbilit1] { outline: 2px solid var(--text-dim); outline-offset: 3px; }

/* ── The panel ──────────────────────────────────────────────────────── */

.help-scrim[b-dvotbilit1] {
    position: fixed;
    inset: 0;
    z-index: 130;
    background: rgb(0 0 0 / 0.32);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.help-panel[b-dvotbilit1] {
    position: fixed;
    inset-block: 0;
    inset-inline-end: 0;
    z-index: 131;

    width: min(420px, 100vw);
    display: flex;
    flex-direction: column;

    /* A full-height overlay uses the page's own gradient. --surface does not
       exist in this theme; var(--surface, #hex) silently falls through to the
       hex and ignores the theme entirely. */
    background: var(--bg-gradient);
    border-inline-start: 1px solid var(--glass-border);
    box-shadow: -12px 0 40px rgb(0 0 0 / 0.35);
    animation: help-in-b-dvotbilit1 .18s ease-out;
}

@keyframes help-in-b-dvotbilit1 {
    from { transform: translateX(6%); opacity: 0; }
    to   { transform: translateX(0);  opacity: 1; }
}

/* Respect a user who has asked for less motion. */
@media (prefers-reduced-motion: reduce) {
    .help-panel[b-dvotbilit1] { animation: none; }
    .help-fab[b-dvotbilit1] { transition: none; }
}

.help-head[b-dvotbilit1] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 14px 16px;
    border-block-end: 1px solid var(--glass-border);
    background: var(--glass-bg);
}

.help-title[b-dvotbilit1] {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 700;
    color: var(--text);
}

.help-spark[b-dvotbilit1] { font-size: 13px; }

.help-head-actions[b-dvotbilit1] { display: flex; align-items: center; gap: 4px; }

.help-lang[b-dvotbilit1] {
    border: 1px solid var(--glass-border);
    background: transparent;
    color: var(--text-dim);
    border-radius: var(--radius-md);
    padding: 3px 8px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
}

.help-lang.on[b-dvotbilit1] {
    background: var(--glass-bg-soft);
    color: var(--text);
}

/* Six languages, so a select rather than six chips — six of those in the header
   leave no room for the mute and close buttons beside them. Styled to match the
   old chips so the header still reads as one row of controls. */
.help-lang-select[b-dvotbilit1] {
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text-main);
    border-radius: var(--radius-md);
    padding: 3px 6px;
    font-size: 11px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}

/* The OPTIONS are deliberately left to the browser. Every background token in
   this theme is a gradient or a translucent glass layer, and none of them is a
   solid colour a dropdown can use — a var() with a hard-coded fallback would
   just ship that fallback past all six themes, which is the trap --surface and
   --lajvard already caused here. The OS default is readable in both. */

.help-mute[b-dvotbilit1] {
    border: 1px solid var(--glass-border);
    background: transparent;
    color: var(--text-dim);
    border-radius: var(--radius-md);
    padding: 3px 7px;
    font-size: 12px;
    cursor: pointer;
    line-height: 1;
}

.help-mute.on[b-dvotbilit1] {
    background: var(--glass-bg-soft);
    color: var(--text);
}

.help-x[b-dvotbilit1] {
    border: none;
    background: transparent;
    color: var(--text-dim);
    font-size: 15px;
    cursor: pointer;
    padding: 4px 6px;
    line-height: 1;
}

.help-x:hover[b-dvotbilit1] { color: var(--text); }

/* ── Conversation ───────────────────────────────────────────────────── */

.help-body[b-dvotbilit1] {
    flex: 1;
    /* A flex child defaults to min-height:auto and grows instead of scrolling —
       without this a long answer pushes the composer off the bottom of the
       screen, which is exactly the trap the Calls drawer hit. */
    min-height: 0;
    overflow-y: auto;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.help-intro[b-dvotbilit1] { display: flex; flex-direction: column; gap: 14px; }

.help-hi[b-dvotbilit1] {
    margin: 0;
    font-size: 13px;
    line-height: 1.65;
    color: var(--text-dim);
}

.help-chips[b-dvotbilit1] { display: flex; flex-wrap: wrap; gap: 6px; }

.help-chip[b-dvotbilit1] {
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text);
    border-radius: 999px;
    padding: 6px 12px;
    font-size: 12px;
    cursor: pointer;
    text-align: start;
    font-family: inherit;
}

.help-chip:hover[b-dvotbilit1] { border-color: var(--text-dim); }

.help-chip.sm[b-dvotbilit1] { font-size: 11px; padding: 4px 10px; }

.help-turn[b-dvotbilit1] { display: flex; flex-direction: column; gap: 8px; }

.help-q[b-dvotbilit1] {
    align-self: flex-end;
    max-width: 88%;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    padding: 8px 12px;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--text);
}

/* The just-transcribed question, before its answer arrives. Dimmed and dashed
   so it reads as provisional rather than as a turn that failed to get one. */
.help-q.is-heard[b-dvotbilit1] {
    opacity: .75;
    border-style: dashed;
}

.help-heard-tag[b-dvotbilit1] {
    font-size: 10px;
    margin-inline-end: 6px;
    opacity: .7;
}

.help-a[b-dvotbilit1] {
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* An ungrounded answer looks different on purpose: "I don't cover that" must
   not wear the same confident styling as a real answer. */
.help-a.is-unsure[b-dvotbilit1] { border-style: dashed; }

.help-a-text[b-dvotbilit1] {
    font-size: 13px;
    line-height: 1.75;
    color: var(--text);
    /* The answer is plain text, never markup — pre-line keeps the model's own
       paragraphs without building HTML out of its output. */
    white-space: pre-line;
    word-break: break-word;
}

.help-go[b-dvotbilit1] {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text);
    border-radius: var(--radius-md);
    padding: 7px 12px;
    font-size: 12px;
    cursor: pointer;
    font-family: inherit;
}

.help-go:hover[b-dvotbilit1] { border-color: var(--text-dim); }

.help-go strong[b-dvotbilit1] { font-weight: 700; }

.help-related[b-dvotbilit1] {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    padding-block-start: 2px;
}

.help-speak[b-dvotbilit1] {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: none;
    background: transparent;
    color: var(--text-dim);
    font-size: 11px;
    cursor: pointer;
    padding: 2px 0;
    font-family: inherit;
}

.help-speak:hover[b-dvotbilit1] { color: var(--text); }
.help-speak.on[b-dvotbilit1] { color: var(--text); }

.help-notice[b-dvotbilit1] {
    font-size: 11.5px;
    line-height: 1.6;
    color: var(--text-dim);
    border: 1px dashed var(--glass-border);
    border-radius: var(--radius-md);
    padding: 8px 10px;
}

/* Three dots, so a wait reads as thinking rather than as a hang. */
.help-thinking[b-dvotbilit1] {
    display: flex;
    gap: 5px;
    padding: 4px 2px;
}

.help-thinking span[b-dvotbilit1] {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-dim);
    animation: help-blink-b-dvotbilit1 1.1s infinite ease-in-out;
}

.help-thinking span:nth-child(2)[b-dvotbilit1] { animation-delay: .18s; }
.help-thinking span:nth-child(3)[b-dvotbilit1] { animation-delay: .36s; }

@keyframes help-blink-b-dvotbilit1 {
    0%, 80%, 100% { opacity: .25; }
    40%           { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .help-thinking span[b-dvotbilit1] { animation: none; opacity: .6; }
}

/* ── Composer ───────────────────────────────────────────────────────── */

.help-foot[b-dvotbilit1] {
    padding: 12px 14px;
    border-block-start: 1px solid var(--glass-border);
    background: var(--glass-bg);
}

.help-compose[b-dvotbilit1] { display: flex; align-items: center; gap: 6px; }

.help-input[b-dvotbilit1] {
    flex: 1;
    min-width: 0;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    padding: 9px 12px;
    color: var(--text);
    font-size: 13px;
    font-family: inherit;
}

.help-input[b-dvotbilit1]::placeholder { color: var(--text-faint); }
.help-input:focus[b-dvotbilit1] { outline: none; border-color: var(--text-dim); }

/* Wider than the send button, and carries a word: hands-free is the headline
   way to use this, so it should not look like one more icon in a row. */
.help-talk[b-dvotbilit1] {
    flex: none;
    height: 36px;
    padding: 0 11px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text);
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
}

.help-talk:hover:not(:disabled)[b-dvotbilit1] { border-color: var(--text-dim); }
.help-talk:disabled[b-dvotbilit1] { opacity: .4; cursor: default; }

.help-mic[b-dvotbilit1],
.help-send[b-dvotbilit1] {
    flex: none;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-md);
    border: 1px solid var(--glass-border);
    background: var(--glass-bg-soft);
    color: var(--text);
    font-size: 14px;
    cursor: pointer;
    display: grid;
    place-items: center;
}

.help-mic:hover:not(:disabled)[b-dvotbilit1],
.help-send:hover:not(:disabled)[b-dvotbilit1] { border-color: var(--text-dim); }

.help-mic:disabled[b-dvotbilit1],
.help-send:disabled[b-dvotbilit1] { opacity: .4; cursor: default; }

/* ── Hands-free conversation ────────────────────────────────────────── */

.help-live[b-dvotbilit1] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.help-live-state[b-dvotbilit1] {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
}

.help-live-txt[b-dvotbilit1] {
    font-size: 12.5px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* One orb, three states. Colour alone would be invisible to about one man in
   twelve, so each state also animates differently: a steady pulse while
   listening, a quick flicker while thinking, a slow swell while speaking. */
.help-live-orb[b-dvotbilit1] {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    flex: none;
    background: var(--text-dim);
}

.help-live-orb.is-listening[b-dvotbilit1] {
    background: var(--pomegranate, #B4372F);
    animation: help-pulse-b-dvotbilit1 1.1s infinite ease-in-out;
}

.help-live-orb.is-thinking[b-dvotbilit1] {
    background: var(--saffron, #E9A13B);
    animation: help-flicker-b-dvotbilit1 .55s infinite ease-in-out;
}

.help-live-orb.is-speaking[b-dvotbilit1] {
    background: var(--lajvard, #23509B);
    animation: help-swell-b-dvotbilit1 1.6s infinite ease-in-out;
}

@keyframes help-flicker-b-dvotbilit1 {
    0%, 100% { opacity: 1; }
    50%      { opacity: .3; }
}

@keyframes help-swell-b-dvotbilit1 {
    0%, 100% { transform: scale(1);    opacity: .85; }
    50%      { transform: scale(1.35); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .help-live-orb[b-dvotbilit1] { animation: none !important; }
}

.help-live-end[b-dvotbilit1] { flex: none; }

/* Why the microphone isn't there. Quiet, but present — the alternative is a
   chat with no voice controls and nothing to explain their absence. */
.help-voice-note[b-dvotbilit1] {
    margin-top: 8px;
    font-size: 11px;
    line-height: 1.5;
    color: var(--text-dim);
}

.help-rec[b-dvotbilit1] {
    display: flex;
    align-items: center;
    gap: 8px;
}

.help-rec-txt[b-dvotbilit1] { font-size: 12.5px; color: var(--text); flex: 1; }

.help-rec-dot[b-dvotbilit1] {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--pomegranate, #B4372F);
    animation: help-pulse-b-dvotbilit1 1s infinite ease-in-out;
    flex: none;
}

@keyframes help-pulse-b-dvotbilit1 {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: .45; transform: scale(.82); }
}

@media (prefers-reduced-motion: reduce) {
    .help-rec-dot[b-dvotbilit1] { animation: none; }
}

/* ── Phones ─────────────────────────────────────────────────────────── */

@media (max-width: 560px) {
    .help-panel[b-dvotbilit1] { width: 100vw; }
    .help-fab[b-dvotbilit1] {
        inset-block-end: 16px;
        inset-inline-end: 16px;
    }
}
/* /Components/Shared/MiniChart.razor.rz.scp.css */
/* A month-by-month bar chart. Sized to sit two or three across in a grid. */

.chart[b-psy76kvzca] {
    position: relative;
    overflow: hidden;
    border: 1px solid var(--glass-border);
    border-radius: var(--r);
    background: var(--glass-bg-soft, rgba(24, 38, 66, 0.4));
    /* Glass, like every other surface in the panel — the charts sit directly
       under the metric cards and a flat panel between them would look like a
       different product. */
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    padding: 12px 14px 10px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* Without this a wide series sets the grid column's minimum width and
       pushes the whole row sideways instead of the bars getting narrower. */
    min-width: 0;
}

/* The lit top edge, as on every other glass surface. */
.chart[b-psy76kvzca]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--glass-edge-lit) 45%, transparent);
    pointer-events: none;
}

/* A bloom in the chart's own colour, tying each card to the series it draws.
   --bar-color is set inline on .bars, so it is lifted here via the parent. */
.chart[b-psy76kvzca]::after {
    content: "";
    position: absolute;
    top: -26px;
    right: -26px;
    width: 76px;
    height: 76px;
    border-radius: 50%;
    background: var(--chart-bloom, transparent);
    filter: blur(22px);
    pointer-events: none;
}

.chart-head[b-psy76kvzca] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    position: relative;
    z-index: 1;
}

.chart-title[b-psy76kvzca] {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ink-muted, #9fb0cc);
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
}

/* Full opacity, unlike the card icons: here it is beside the title at reading
   size rather than floating behind a number, so dimming it would just make it
   look broken. */
.chart-icon[b-psy76kvzca] {
    font-size: 12px;
    line-height: 1;
    flex: 0 0 auto;
}

.chart-note[b-psy76kvzca] {
    font-size: 10.5px;
    color: var(--ink-faint, #6f819c);
    white-space: nowrap;
}

.chart-empty[b-psy76kvzca] {
    height: 96px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11.5px;
    color: var(--ink-faint, #6f819c);
}

.bars[b-psy76kvzca] {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    /* Each column may shrink to nothing rather than overflowing the card —
       twelve months have to fit whatever width the grid gives this. */
    min-width: 0;
    /* Above the corner bloom, which is a blurred pseudo-element painted after
       the normal flow and would otherwise sit on top of the tallest bars. */
    position: relative;
    z-index: 1;
}

.bar-col[b-psy76kvzca] {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
}

/* The full-height lane a bar grows inside. Fixed height so every chart in a row
   has its baseline at the same place — bars that each size to their own content
   make two charts side by side impossible to compare. */
.bar-track[b-psy76kvzca] {
    width: 100%;
    height: 78px;
    display: flex;
    align-items: flex-end;
    background: rgba(255, 255, 255, 0.03);
    border-radius: 3px 3px 0 0;
    overflow: hidden;
}

.bar-fill[b-psy76kvzca] {
    width: 100%;
    background: linear-gradient(to top, var(--bar-color), color-mix(in srgb, var(--bar-color) 55%, white));
    border-radius: 3px 3px 0 0;
    transition: height 0.25s ease;
}

/* A month with genuinely nothing in it. The empty track still shows, so the
   month is visibly present and empty rather than missing from the axis. */
.bar-fill.is-zero[b-psy76kvzca] { background: none; }

.bar-val[b-psy76kvzca] {
    font-size: 9px;
    font-weight: 700;
    color: var(--ink-dim, #b9c7de);
    line-height: 1;
    /* Clipped rather than wrapped: a two-line value would shove this column's
       baseline out of line with its neighbours. */
    overflow: hidden;
    max-width: 100%;
    white-space: nowrap;
}

.bar-lbl[b-psy76kvzca] {
    font-size: 8.5px;
    color: var(--ink-faint, #6f819c);
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    max-width: 100%;
}
/* /Components/Shared/Modal.razor.rz.scp.css */
.scrim[b-lnghlke1q6] {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: grid;
    place-items: center;
    padding: 1.5rem;
    background: rgba(7, 12, 22, 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    animation: scrim-in-b-lnghlke1q6 0.16s ease-out;
}

/* The login card's glass, lifted: same blur, same lit edge, same glow. */
.sheet[b-lnghlke1q6] {
    width: min(560px, 100%);
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
    padding: 1.4rem;
    background: var(--glass-strong);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-lift), 0 0 25px var(--accent-glow-soft);
    animation: sheet-in-b-lnghlke1q6 0.2s cubic-bezier(0.2, 0.9, 0.3, 1);
}

.sheet-head[b-lnghlke1q6] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

/* The form is the only part allowed to scroll — the header and the commit
   buttons stay put, so the action is always reachable. */
.sheet-body[b-lnghlke1q6] {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    overflow-y: auto;
    min-height: 0;
}

.sheet-foot[b-lnghlke1q6] {
    display: flex;
    justify-content: flex-start;
    gap: 0.6rem;
    padding-top: 0.2rem;
    border-top: 1px solid var(--glass-edge);
    margin-top: 0.2rem;
    padding-top: 1rem;
}

@keyframes scrim-in-b-lnghlke1q6 {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes sheet-in-b-lnghlke1q6 {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .scrim[b-lnghlke1q6], .sheet[b-lnghlke1q6] { animation: none; }
}
/* /Components/Shared/MonthGrid.razor.rz.scp.css */
/* The month grid, beside the component that draws it.
   The service palette (.sw-*) stays shared in app.css. */

/* ---------- Month grid ---------- */

.month-dows[b-pr8um6zvem] {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
    margin-bottom: 6px;
}

.mdow[b-pr8um6zvem] {
    text-align: center;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-faint);
}

.month-grid[b-pr8um6zvem] {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
}

.mcell[b-pr8um6zvem] {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-height: 92px;
    padding: 6px;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    min-width: 0;

    /* The blur is what makes this read as glass rather than as a flat tint. The
       background token alone was already here; without the filter the month sat
       visibly flatter than the week beside it. */
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}

/* Padding days keep the grid rectangular but must not draw the eye. */
.mcell-out[b-pr8um6zvem] { opacity: 0.3; }

/* Today is lit — the cell the owner is standing in.
   The border is the ACCENT, not --text-dim: a grey edge reads as a disabled
   cell rather than the current one, and the week card next door uses the accent
   for the same job. "Today" should look like one thing across the schedule. */
.mcell-today[b-pr8um6zvem] {
    background: var(--accent-glow-soft);
    border-color: var(--accent-glow);
    box-shadow: 0 0 16px var(--accent-glow-soft);
}

.mcell-head[b-pr8um6zvem] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px;
}

.mcell-date[b-pr8um6zvem] { font-size: 11.5px; font-weight: 700; color: var(--text-dim); }
.mcell-today .mcell-date[b-pr8um6zvem] { color: #E9A13B; }

/* The day's takings, right where the eye lands. */
.mcell-money[b-pr8um6zvem] { font-size: 9.5px; font-weight: 700; color: #F2BE72; }

.mchip[b-pr8um6zvem] {
    display: block;
    width: 100%;
    padding: 2px 5px;
    border: none;
    /* 3px, matching the week card. At two pixels a hue reads as a grey hairline
       on dark glass whatever colour it is — there simply isn't enough of it to
       see, and this strip is the only place a month chip names its service. */
    border-left: 3px solid transparent;
    border-radius: 4px;
    font-family: inherit;
    font-size: 9.5px;
    color: var(--text-main);
    text-align: left;
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    /* Glass, like the week. Kept lighter than the day card behind it so a row of
       chips reads as sitting ON the cell rather than punching holes in it. */
    background: var(--glass-bg-soft);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: transform .12s, filter .12s;
}

.mchip:hover[b-pr8um6zvem] { transform: translateX(1px); filter: brightness(1.25); }

/* ---------- Service colour ----------

   The month used to draw every booking the same: .mchip set border-left to
   `transparent` and nothing ever filled it, so the sw-* class on the element
   did nothing at all. A month of grey chips says a salon does one kind of work.

   Same three states and the same variables as the week card, so a booking is
   the same colour whichever view it is read in. Two views disagreeing about
   what blue means are two calendars, not two views of one. */
.mchip.chip-ok[b-pr8um6zvem] {
    background: var(--svc-dim);
    border-left-color: var(--svc-lit);
    box-shadow: inset 3px 0 8px -3px var(--svc-lit);
}

/* Not yet a commitment: dashed, and the amber every "pending" uses. */
.mchip.chip-warn[b-pr8um6zvem] {
    background: var(--svc-dim);
    border-left-color: #FBBF24;
    border-left-style: dashed;
}

/* Cancelled stays visible but stops competing for attention. */
.mchip.chip-off[b-pr8um6zvem] {
    background: transparent;
    border-left-color: var(--text-faint);
    border-left-style: dashed;
    opacity: 0.5;
    text-decoration: line-through;
}

.mmore[b-pr8um6zvem] { font-size: 9px; color: var(--text-faint); padding-left: 5px; }


@media (max-width: 760px) {
    .month-grid[b-pr8um6zvem], .month-dows[b-pr8um6zvem] { font-size: 9px; }
    .mcell[b-pr8um6zvem] { min-height: 62px; }
    .mchip[b-pr8um6zvem] { display: none; }
}
/* /Components/Shared/OwnNumberCard.razor.rz.scp.css */
/* Choosing a number to buy.

   THESE CLASSES HAD NO CSS AT ALL. The markup used .num-grid / .num-option and
   nothing defined them, so the browser laid the buttons out inline — a row of
   phone numbers running across the page, which is both the hardest possible
   shape to scan and impossible to tell "selected" from "not". */

/* A LIST, ONE PER ROW. Phone numbers are compared digit by digit, and a reader
   doing that needs them stacked so the digits line up vertically. Side by side
   they have to be re-found each time. */
.num-grid[b-cfzxp0b2x0] {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 12px;
    /* Long lists scroll inside the card rather than pushing the buy button off
       the page — a search can return dozens. */
    max-height: 320px;
    overflow-y: auto;
}

.num-option[b-cfzxp0b2x0] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    text-align: left;
    padding: 11px 14px;
    border-radius: 10px;
    border: 1px solid var(--glass-edge);
    background: var(--glass-strong);
    color: var(--ink);
    cursor: pointer;
    font: inherit;
    transition: border-color .12s, background .12s;
}

.num-option:hover[b-cfzxp0b2x0] {
    border-color: var(--accent);
}

/* The selected one has to be obvious at a glance: this is the number about to
   be BOUGHT, and a faint outline is not enough to check before spending. */
.num-option.is-picked[b-cfzxp0b2x0] {
    border-color: var(--accent);
    background: var(--sunken);
    box-shadow: inset 3px 0 0 var(--accent);
}

.num-value[b-cfzxp0b2x0] {
    font-variant-numeric: tabular-nums;
    font-size: 15px;
    letter-spacing: .01em;
}

.num-place[b-cfzxp0b2x0] {
    font-size: 12px;
    text-align: right;
}

/* The area-code primer. Sits above the search box because it answers the
   question the box asks, and an owner who has never bought a phone number does
   not know that 416 and 647 are the same city. */
.ac-help[b-cfzxp0b2x0] {
    margin: 10px 0 0;
    padding: 10px 12px;
    border-radius: 10px;
    background: var(--sunken);
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--ink-dim);
}

.ac-help strong[b-cfzxp0b2x0] {
    color: var(--ink);
}

.ac-help .ac-row + .ac-row[b-cfzxp0b2x0] {
    margin-top: 4px;
}
/* /Components/Shared/PlanCards.razor.rz.scp.css */
/* ============================================================
   PlanCards.razor.css — the plan line-up, shared by the public
   /plans page and the business Billing page.

   Scoped to the COMPONENT, which is why these rules live here
   rather than in Plans.razor.css: Blazor's isolation attribute
   is per-component, so a page's stylesheet cannot reach markup
   a child component renders. Card styling on the page would
   have left the Billing copy completely unstyled.

   Every colour is a theme.css token, so the cards follow
   blue/gold/lilac like the rest of the panel.
   ============================================================ */

/* ---------- The cards ---------- */

.plans-grid[b-7uuw89m0tn] {
    max-width: 1120px;
    margin: 0 auto;
    display: grid;
    /* auto-fit, not a fixed 3: the number of plans comes from the database and
       an admin can add or retire one. A hard-coded three-column rule leaves a
       gaping hole the day there are two. */
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 20px;
    /* The featured card is scaled up and would be clipped by the grid's edge. */
    padding: 14px 0;
}

.plan-card[b-7uuw89m0tn] {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 30px 26px 26px;
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-xl);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.42);
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.plan-card:hover[b-7uuw89m0tn] {
    transform: translateY(-4px);
    box-shadow: 0 26px 60px rgba(0, 0, 0, 0.5), 0 0 22px var(--accent-glow-soft);
}

/* The middle plan, lifted. Chosen positionally in the component, so the
   emphasis follows the price list instead of being pinned to one plan id. */
.plan-card.is-featured[b-7uuw89m0tn] {
    border-color: var(--saffron);
    box-shadow: 0 24px 56px rgba(0, 0, 0, 0.5), 0 0 26px rgba(233, 161, 59, 0.28);
}

@media (min-width: 900px) {
    .plan-card.is-featured[b-7uuw89m0tn] { transform: scale(1.035); }
    .plan-card.is-featured:hover[b-7uuw89m0tn] { transform: scale(1.035) translateY(-4px); }
}

.plan-flag[b-7uuw89m0tn] {
    position: absolute;
    top: -11px;
    left: 26px;
    padding: 3px 12px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #2b1c0f;
    background: var(--saffron);
    border-radius: 999px;
    box-shadow: 0 4px 14px rgba(233, 161, 59, 0.4);
}

.plan-name[b-7uuw89m0tn] {
    font-size: 19px;
    font-weight: 700;
}

.plan-blurb[b-7uuw89m0tn] {
    margin-top: 4px;
    font-size: 12.5px;
    color: var(--text-faint);
    /* Two cards whose blurbs wrap differently would misalign every price below
       them; reserving the second line keeps the row on one baseline. */
    min-height: 2.6em;
}

.plan-price[b-7uuw89m0tn] {
    display: flex;
    align-items: baseline;
    gap: 3px;
    margin: 14px 0 18px;
}

.price-cur[b-7uuw89m0tn] {
    font-size: 20px;
    font-weight: 600;
    color: var(--ink-dim);
}

.price-num[b-7uuw89m0tn] {
    font-size: 44px;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.02em;
}

/* The currency, beside the figure rather than under it.
   Smaller than the leading "$" and not bold: it must be legible without
   competing with the number, which is what the eye is here for. Letter-spaced
   because a three-letter uppercase word set this small reads as a smudge. */
.price-usd[b-7uuw89m0tn] {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--text-faint);
    margin-left: 2px;
}

.price-per[b-7uuw89m0tn] {
    font-size: 13px;
    color: var(--text-faint);
    margin-left: 3px;
}

/* ---------- The figures that differ ---------- */

.plan-meters[b-7uuw89m0tn] {
    margin: 0 0 22px;
    padding: 16px 0;
    border-top: 1px solid var(--glass-border);
    border-bottom: 1px solid var(--glass-border);
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.plan-meters > div[b-7uuw89m0tn] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.plan-meters dt[b-7uuw89m0tn] {
    font-size: 12.5px;
    color: var(--text-faint);
}

.plan-meters dd[b-7uuw89m0tn] {
    margin: 0;
    font-size: 13px;
    text-align: right;
}

.plan-meters strong[b-7uuw89m0tn] {
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
}

/* ---------- Call to action ---------- */

.plan-cta[b-7uuw89m0tn] {
    display: block;
    /* Pushed to the bottom so buttons line up across cards whose blurbs differ
       in height — a ragged row of buttons reads as a broken layout. */
    margin-top: auto;
    padding: 12px;
    text-align: center;
    text-decoration: none;
    font-size: 14.5px;
    font-weight: 700;
    border-radius: var(--radius-md);
    transition: transform 0.2s, box-shadow 0.2s;

    /* The public page renders this as an <a>, the panel as a <button>. A button
       brings its own font, its own width rule and a border nobody asked for, so
       the two would otherwise look like different controls doing the same job. */
    width: 100%;
    border: none;
    font-family: inherit;
    cursor: pointer;
}

/* Disabled while a checkout is opening. Kept legible rather than greyed to the
   floor: the card the owner just clicked is the one they are reading. */
.plan-cta:disabled[b-7uuw89m0tn] {
    cursor: default;
    opacity: 0.55;
}

.plan-cta:disabled:hover[b-7uuw89m0tn] { transform: none; }

.cta-solid[b-7uuw89m0tn] {
    background: var(--accent-gradient);
    color: var(--accent-text-on-fill);
    box-shadow: 0 0 18px var(--accent-glow);
}

.cta-ghost[b-7uuw89m0tn] {
    background: transparent;
    color: var(--ink);
    border: 1px solid var(--glass-border);
}

.plan-cta:hover[b-7uuw89m0tn] { transform: translateY(-2px); }
.cta-ghost:hover[b-7uuw89m0tn] { border-color: var(--accent-glow); }

.plan-fine[b-7uuw89m0tn] {
    margin-top: 12px;
    font-size: 11.5px;
    line-height: 1.7;
    text-align: center;
    color: var(--text-faint);
}

/* ---------- Usage, inside the owner's own card ----------

   The meter sits with the allowance it spends. It is the only thing on these
   cards that is about THIS month rather than about the price list, so it gets a
   rule above it to read as a different kind of fact. */

.plan-usage[b-7uuw89m0tn] {
    margin: 12px 0 4px;
    padding-top: 12px;
    border-top: 1px dashed var(--glass-border);
}

.plan-usage .meter[b-7uuw89m0tn] {
    height: 7px;
    border-radius: 999px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.10);
}

.plan-usage .meter-fill[b-7uuw89m0tn] {
    height: 100%;
    border-radius: 999px;
    background: var(--accent-gradient);
    transition: width 0.3s;
}

/* Over the allowance is the one state worth colouring: it is money. */
.plan-usage .meter-fill.meter-over[b-7uuw89m0tn] {
    background: linear-gradient(90deg, #d4685f, #B4372F);
}

.plan-usage .usage-line[b-7uuw89m0tn] {
    margin-top: 7px;
    font-size: 11.5px;
    line-height: 1.6;
    text-align: center;
    color: var(--text-dim);
}

.plan-usage .over[b-7uuw89m0tn] {
    color: #e08b83;
    font-weight: 700;
}

.plan-usage .faint[b-7uuw89m0tn] { color: var(--text-faint); }


/* ---------- Empty / error state ---------- */

.plans-empty[b-7uuw89m0tn] {
    padding: 1.5rem;
    text-align: center;
    font-size: 13.5px;
    color: var(--text-faint);
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
}

/* ---------- Compact: inside the signed-in panel ----------

   Narrower cards and tighter type. The owner is comparing three numbers they
   already understand, not being introduced to the product, so the cards should
   take a fraction of the page rather than owning it. */

.plans-grid.is-compact[b-7uuw89m0tn] {
    max-width: 100%;
    gap: 14px;
    padding: 10px 0;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

.is-compact .plan-card[b-7uuw89m0tn] {
    padding: 20px 18px 18px;
    border-radius: var(--radius-lg);
}

.is-compact .plan-name[b-7uuw89m0tn] { font-size: 15px; }
.is-compact .price-num[b-7uuw89m0tn] { font-size: 30px; }
.is-compact .price-cur[b-7uuw89m0tn] { font-size: 15px; }
/* After .price-cur, which this shares a class with — the compact rule above
   would otherwise size USD like the leading "$" and make it the loudest thing
   on the line. */
.is-compact .price-usd[b-7uuw89m0tn] { font-size: 11.5px; }
.is-compact .plan-price[b-7uuw89m0tn] { margin: 8px 0 12px; }

.is-compact .plan-meters[b-7uuw89m0tn] {
    margin-bottom: 0;
    padding: 12px 0;
    gap: 8px;
}

.is-compact .plan-meters dt[b-7uuw89m0tn] { font-size: 11.5px; }
.is-compact .plan-meters dd[b-7uuw89m0tn] { font-size: 12px; }
.is-compact .plan-meters strong[b-7uuw89m0tn] { font-size: 13.5px; }
.is-compact .plan-fine[b-7uuw89m0tn] { font-size: 11px; margin-top: 10px; }

/* The featured lift is a sales device; inside the panel it would just make one
   card taller than its neighbours for no reason the owner benefits from. */
.is-compact .plan-card.is-featured[b-7uuw89m0tn] { transform: none; }
.is-compact .plan-card:hover[b-7uuw89m0tn] { transform: none; }

/* ---------- The tenant's own plan ----------

   Marked, not sold. This is the one question an owner opens the page with, so
   it gets the accent — and it is why "Most popular" is suppressed whenever a
   current plan is known: two badges competing is us advertising to somebody who
   has already bought. */

.plan-card.is-mine[b-7uuw89m0tn] {
    border-color: var(--accent-glow);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.42), 0 0 20px var(--accent-glow-soft);
}

.plan-flag.flag-mine[b-7uuw89m0tn] {
    color: var(--accent-text-on-fill);
    background: var(--accent-gradient);
    box-shadow: 0 4px 14px var(--accent-glow-soft);
}

/* ---------- Responsive ---------- */

@media (max-width: 640px) {
    .plan-card[b-7uuw89m0tn] { padding: 26px 20px 22px; }
    /* On one column the blurbs no longer need to align across cards, so the
       reserved second line is just a gap. */
    .plan-blurb[b-7uuw89m0tn] { min-height: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .plan-card[b-7uuw89m0tn],
    .plan-cta[b-7uuw89m0tn] {
        transition: none;
    }

    .plan-card:hover[b-7uuw89m0tn],
    .plan-cta:hover[b-7uuw89m0tn] {
        transform: none;
    }

    .plan-card.is-featured:hover[b-7uuw89m0tn] { transform: scale(1.035); }
}
/* /Components/Shared/Toast.razor.rz.scp.css */
/* Bottom-right, above everything, out of the way of the content it refers to. */
.toast-host[b-gqospma365] {
    position: fixed;
    right: 18px;
    bottom: 18px;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
}

.toast[b-gqospma365] {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 10px 14px;
    min-width: 220px;
    max-width: 340px;
    border-radius: var(--radius-md);
    /* The status colour carries the toast, not just its icon dot. Plain glass is
       navy in the blue theme, so a toast with only a green dot read as "navy
       card" — the good news was a speck. A tinted wash and a lit left edge, per
       status, say "booking" or "cancelled" at a glance without shouting.

       --toast-accent is set by the status class below; both edges read from it. */
    border: 1px solid var(--glass-border);
    border-left: 3px solid var(--toast-accent, var(--glass-border));
    background:
        linear-gradient(90deg, var(--toast-wash, transparent), transparent 60%),
        var(--glass-bg);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.4);
    font-size: 12.5px;
    color: var(--text-main);
    /* Slides up from below on arrival — the eye catches the motion without the
       toast stealing focus from what the owner is doing. */
    animation: toast-in-b-gqospma365 0.22s ease-out;
}

/* A new booking is good news — the panel's green. */
.toast-info[b-gqospma365] {
    --toast-accent: #4ADE80;
    --toast-wash: rgba(74, 222, 128, 0.14);
}

/* A cancellation is not an error, but it is not celebration either — amber. */
.toast-warn[b-gqospma365] {
    --toast-accent: #E9A13B;
    --toast-wash: rgba(233, 161, 59, 0.14);
}

.toast-icon[b-gqospma365] {
    flex: none;
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    font-size: 11px;
    font-weight: 700;
}

/* A new booking is good news — the panel's green. */
.toast-info .toast-icon[b-gqospma365] {
    color: #062;
    background: #4ADE80;
    box-shadow: 0 0 10px rgba(74, 222, 128, 0.5);
}

/* A cancellation is not an error, but it is not celebration either — amber. */
.toast-warn .toast-icon[b-gqospma365] {
    color: #3a2600;
    background: #E9A13B;
    box-shadow: 0 0 10px rgba(233, 161, 59, 0.5);
}

.toast-text[b-gqospma365] { line-height: 1.4; }

@keyframes toast-in-b-gqospma365 {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .toast[b-gqospma365] { animation: none; }
}
/* /Components/Shared/WeekCards.razor.rz.scp.css */
/* The week's day cards, beside the component that draws them.
   The service palette (.sw-*) stays shared in app.css. */

/* ---------- Week: a grid of day cards ---------- */

/* Cards that wrap, not seven fixed columns. A booking has to carry a time, a
   name, a service and a source badge — 1/7th of the width can't hold that, and
   on a phone seven columns are unreadable slivers. */
/* Seven across on a desktop, because a week that wraps 5-then-2 stops reading
   as a week — the shape of the row IS the information. It only breaks into
   fewer columns when the cards would get too narrow to hold a name. */
.day-grid[b-3735rtfizp] {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 8px;
}


.daycard[b-3735rtfizp] {
    display: flex;
    flex-direction: column;
    min-height: 104px;
    padding: 8px 9px;
    background: var(--glass-bg-soft);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}

/* Today is lit — the card the owner is standing in. */
.daycard-today[b-3735rtfizp] {
    background: var(--accent-glow-soft);
    border-color: var(--accent-glow);
    box-shadow: 0 0 16px var(--accent-glow-soft);
}

/* Days already gone stay in the grid so the week reads as a week.

   NOT opacity: the week runs Monday→Sunday, so fading the past fades everything
   to the LEFT of today — the page reads as a left-to-right brightness gradient
   that has nothing to do with the data, and it slides across the week as the
   days pass. Worse, opacity fades the bookings too: a past day's colours, names
   and takings go milky, and last Tuesday's revenue is still real money.

   The date recedes instead. That marks the day as done without touching what is
   written on it. */
.daycard-past .dc-dow[b-3735rtfizp],
.daycard-past .dc-date[b-3735rtfizp] { color: var(--text-faint); }

.daycard-head[b-3735rtfizp] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px;
    padding-bottom: 6px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--glass-border);
}

.dc-when[b-3735rtfizp] { display: flex; align-items: baseline; gap: 6px; }

.dc-dow[b-3735rtfizp] {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-faint);
}

.dc-date[b-3735rtfizp] { font-size: 14px; font-weight: 700; color: var(--text-main); }

.dc-today[b-3735rtfizp] {
    padding: 0 6px;
    border-radius: 999px;
    background: var(--accent-gradient);
    color: var(--accent-text-on-fill);
    font-size: 8px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* The day's takings: the number an owner scans a week for. */
.dc-money[b-3735rtfizp] { font-size: 11px; font-weight: 700; color: #F2BE72; }

.dc-none[b-3735rtfizp] {
    flex: 1;
    display: grid;
    place-items: center;
    color: var(--text-faint);
    font-size: 10.5px;
}

.dc-list[b-3735rtfizp] { display: flex; flex-direction: column; gap: 4px; }

/* ---------- One booking in a day card ---------- */

/* The whole row is the button — a small "details" link would be a miss target
   on a phone, and this is the thing the owner reaches for. */
.bk[b-3735rtfizp] {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
    padding: 5px 7px;
    border: none;
    /* 4px, not 2: at two pixels on dark glass a colour reads as a grey hairline
       whatever hue it is — there isn't enough of it to see. This strip is the
       only place the week names its service, so it has to actually carry. */
    border-left: 4px solid transparent;
    border-radius: var(--radius-sm);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: transform .12s, filter .12s;
}

.bk:hover[b-3735rtfizp] { transform: translateX(2px); filter: brightness(1.25); }

.bk-time[b-3735rtfizp] { font-size: 10.5px; font-weight: 700; flex: none; }

.bk-main[b-3735rtfizp] { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.bk-name[b-3735rtfizp] {
    font-size: 11px;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The name given on the call, when it isn't the contact's. Quieter than the
   contact name — it is a "by the way", and the card is only so wide. */
.bk-alias[b-3735rtfizp] { font-size: 10px; }

.bk-sub[b-3735rtfizp] {
    font-size: 9px;
    color: var(--text-faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Where it came from, as a glyph: on a row this size a word would crowd out the
   customer's name, and the icon is the same one used in the dialog. */
.src[b-3735rtfizp] {
    flex: none;
    font-size: 11px;
    opacity: 0.75;
}

/* The service's colour carries the row; status modifies it rather than replacing
   it. Two facts, two channels: hue says WHAT, treatment says WHETHER. Before
   this, green-means-confirmed used up the colour channel entirely and every
   service looked alike.

   The strip is the LIT tone, not the base: --svc is tuned to sit behind text as
   a fill, and behind glass at a few pixels wide it goes muddy. The glow is what
   makes it read as lit rather than painted — the same trick the today-pill and
   the staff dot already use. */
.chip-ok[b-3735rtfizp] {
    background: var(--svc-dim);
    border-left-color: var(--svc-lit);
    box-shadow: inset 3px 0 8px -3px var(--svc-lit);
}
.chip-ok .bk-time[b-3735rtfizp], .chip-ok .chip-time[b-3735rtfizp] { color: var(--svc-lit); }

/* Not yet a commitment: dashed, and the amber of every "pending" in the panel. */
.chip-warn[b-3735rtfizp] {
    background: var(--svc-dim);
    border-left-color: #FBBF24;
    border-left-style: dashed;
}
.chip-warn .bk-time[b-3735rtfizp], .chip-warn .chip-time[b-3735rtfizp] { color: #FDE68A; }

/* Cancelled stays visible but stops competing. */
/* Cancelled stays visible but stops competing — the history remains, the eye
   skips it. */
.chip-off[b-3735rtfizp] {
    background: rgba(248, 113, 113, 0.08);
    border-left-color: rgba(248, 113, 113, 0.5);
    opacity: 0.6;
}
.chip-off .bk-name[b-3735rtfizp] { text-decoration: line-through; }
.chip-off .bk-time[b-3735rtfizp], .chip-off .chip-time[b-3735rtfizp] { color: var(--text-error); }


/* ---------- Responsive ---------- */

/* Seven columns only survive while a card can still hold a customer's name.
   Below that the week folds — losing the row shape beats losing the words. */
@media (max-width: 1250px) {
    .day-grid[b-3735rtfizp] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
    .day-grid[b-3735rtfizp] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
    .day-grid[b-3735rtfizp] { grid-template-columns: minmax(0, 1fr); }
}
