@charset "UTF-8";
/* ############################################################################
   QLYNIC PATIENT PORTAL  ·  qlynic-ui.css
   THE DESIGN SYSTEM  ("Qlynic UI")
   ----------------------------------------------------------------------------
   THEME ........ AURORA GLASS v8  ·  refined descendant of the Qlynic app's
                  "Aurora Noir" (essentials.css) and the patient portal's
                  "Aurora Glass v7" (patient-master.css).
   FOR .......... Patients. Not staff. Every decision below is tuned for people
                  reading medical information — often anxious, often one-handed
                  on a phone. Calm beats dense. Legible beats clever.
   PREFIX ....... q-  /  qbtn        (no collision with master pm-, nor with
                  page namespaces ua-, qpr-, etc.)
   LOAD ORDER ... qlynic-ui.css  ->  patient-master.css  ->  <page>.css
                  This file is the vocabulary. The master writes the shell.
                  The page writes the sentences. Never the reverse.

   WHAT'S IN ..... every reusable ATOM and MOLECULE: buttons, fields, panels,
                  modals, drawers, toasts, tables, tabs, plus the patient-domain
                  components (appointment cards, result readouts, message
                  threads, timelines, document rows, care team cards).
   WHAT'S NOT .... page LAYOUT. A page's grid/hero/feed lives in its own sheet.

   HOW TO RETHEME  Edit section 2 ONLY. Every component reads tokens, so the
                  whole portal reskins from one block. Tokens are safe to tune;
                  component RULES ripple into shipped pages — touch sparingly.

   COLOUR METHOD . The palette is not eyeballed. Every value was placed in OKLCH
                  and checked for (a) even perceptual steps between surfaces,
                  (b) a tight lightness band across semantics so no status
                  colour shouts louder than another, (c) WCAG contrast. Notable
                  fixes vs the app sheet:
                    · semantic lightness spread cut 0.109 -> 0.064
                    · aurora sweep stops levelled to L=0.790, killing the dark
                      band that used to appear mid-gradient
                    · primary button flattened: the old 180deg gloss ramp
                      (dL 0.079) is gone
   ############################################################################ */


/* ============================================================================
   1.  GLOBAL TOKENS   (theme-agnostic: type / space / radius / motion / z)
   ============================================================================ */
:root {
    /* --- Type -------------------------------------------------------------
       Plus Jakarta Sans is already loaded by Patient.Master and is the warmer,
       more humane face of the two candidates — the right register for patients.
       To move the portal onto the app's Geist, swap the first family only. */
    --font: "Plus Jakarta Sans", "Geist", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-mono: "JetBrains Mono", "Geist Mono", ui-monospace, "SF Mono", "Cascadia Code", monospace;
    /* Patient-facing base is 15px, not the app's 14px. One step up buys real
       comfort for older eyes and costs almost no density. */
    --font-size-display: 2.25rem; /* 36px  hero numerals        */
    --font-size-xxl: 1.625rem; /* 26px  page titles          */
    --font-size-xl: 1.3125rem; /* 21px  section titles       */
    --font-size-lg: 1.0625rem; /* 17px  card titles          */
    --font-size-base: 0.9375rem; /* 15px  body                 */
    --font-size-sm: 0.875rem; /* 14px  secondary            */
    --font-size-xs: 0.8125rem; /* 13px  labels               */
    --font-size-xxs: 0.75rem; /* 12px  micro / kicker       */
    --fw-regular: 400;
    --fw-medium: 500;
    --fw-semibold: 600;
    --fw-bold: 700;
    --fw-black: 800;
    --lh-tight: 1.18;
    --lh-snug: 1.38;
    --lh-base: 1.58; /* generous — this is reading matter */
    --ls-tight: -.022em;
    --ls-snug: -.012em;
    --ls-wide: .04em;
    --ls-caps: .09em;
    /* --- Space scale (4px base; use these, never magic numbers) --- */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 20px;
    --sp-6: 24px;
    --sp-7: 32px;
    --sp-8: 40px;
    --sp-9: 48px;
    --sp-10: 64px;
    /* --- Radii --- */
    --radius-xs: 8px;
    --radius-sm: 10px;
    --radius-md: 13px;
    --radius-lg: 18px;
    --radius-xl: 22px;
    --radius-2xl: 28px;
    --radius-pill: 999px;
    /* Asymmetric radius: the patient portal's inherited signature. Opt-in via
       .q-asym so it stays a deliberate accent instead of ambient noise. */
    --radius-asym: 16px 12px 12px 16px;
    --radius-asym-lg: 22px 16px 16px 22px;
    /* --- Motion --- */
    --ease: cubic-bezier(.4, 0, .2, 1);
    --ease-out: cubic-bezier(.16, 1, .3, 1);
    --ease-spring: cubic-bezier(.34, 1.4, .5, 1);
    --timing-fast: .14s;
    --timing: .22s;
    --timing-slow: .38s;
    /* --- Z ladder --- */
    --z-base: 1;
    --z-sticky: 100;
    --z-menu: 300;
    --z-drawer: 5000;
    --z-modal: 6000;
    --z-toast: 9000;
}


/* ============================================================================
   2.  AURORA GLASS v8  ·  THEME TOKENS   ·   EDIT THIS BLOCK TO RETHEME
   ----------------------------------------------------------------------------
   Material model — why this reads expensive:
     · SURFACES ARE STEPPED, NOT TRANSPARENT-BY-DEFAULT. Six opaque gunmetal
       levels on an obsidian ground, each a measured perceptual step above the
       last. Glass is applied on top of that, for floating things only.
     · LIGHT COMES FROM ABOVE. Every raised surface gets a 1px top edge-light
       and a layered shadow. Hover brightens and lifts. Nothing glows.
     · ONE ACCENT, USED SPARINGLY. Indigo #7289EE leads. The aurora sweep is
       reserved for focal moments — never for chrome.
   ============================================================================ */
:root, .theme-dark {
    /* ── 2.1  CANVAS ───────────────────────────────────────────────────── */
    --bg-base: #040710;
    --bg-elevated: #070B16;
    /* Ambient bloom. Fixed, low-alpha, drifting in from the corners so panels
       have something to sit against. Applied to <body> in section 3. */
    --bg-gradient: radial-gradient(1180px 740px at 10% -14%, rgba(114,137,238,.15) 0%, transparent 58%), radial-gradient(920px 600px at 92% -8%, rgba(68,221,217,.075) 0%, transparent 54%), radial-gradient(780px 540px at 82% 112%, rgba(249,144,196,.05) 0%, transparent 58%), radial-gradient(660px 480px at 2% 96%, rgba(197,154,250,.045) 0%, transparent 62%);
    /* ── 2.2  SURFACES  (even OKLCH steps: .178 .208 .238 .268 .309 .358) ─ */
    --surface-0: #0D111A; /* deepest inset: wells, recessed fields   */
    --surface-1: #131821; /* quiet: rails, rows, toolbars            */
    --surface-2: #1A1F28; /* raised quiet: bars, footers             */
    --surface-3: #212630; /* >>> THE PANEL MATERIAL                  */
    --surface-4: #2B303B; /* raised: menus, popovers, hovered cards  */
    --surface-5: #373D47; /* highest: modal / drawer / tooltip body  */
    --surface-tint: #1B2033; /* indigo-tinted pane for focal cards      */
    /* ── 2.2b  GLASS  (floating things only — never fields) ─────────────── */
    --glass-blur: 20px;
    --glass-saturate: 155%;
    --glass-panel: color-mix(in srgb, var(--surface-3) 64%, transparent);
    --glass-panel-hover: color-mix(in srgb, var(--surface-4) 70%, transparent);
    --glass-card: color-mix(in srgb, var(--surface-3) 56%, transparent);
    --glass-raised: color-mix(in srgb, var(--surface-4) 74%, transparent);
    --glass-modal: color-mix(in srgb, var(--surface-5) 82%, transparent);
    --glass-note: color-mix(in srgb, var(--surface-2) 62%, transparent);
    --glass-edge: rgba(255,255,255,.09);
    --glass-edge-strong: rgba(255,255,255,.15);
    /* ── 2.3  BORDERS ──────────────────────────────────────────────────── */
    --border-subtle: rgba(158,170,215,.09);
    --border-default: rgba(164,176,222,.15);
    --border-strong: rgba(172,184,230,.24);
    --border-interactive: rgba(114,137,238,.45);
    /* ── 2.4  TEXT  (all verified >= 4.5:1 on the panel material) ───────── */
    --text-primary: #F2F4F9; /* 13.8:1 on panel  */
    --text-secondary: #D3D7DE; /* 10.5:1           */
    --text-muted: #9EA2AB; /*  5.9:1           */
    --text-faint: #7B808A; /*  3.8:1 — decorative only, never body */
    --text-on-accent: #FFFFFF;
    --text-on-light: #10131C; /* for pastel / inverted fills */
    /* ── 2.5  BRAND  (indigo H=272 — bridges app periwinkle & portal sky) ─ */
    --primary: #7289EE;
    --primary-bright: #89A1FF;
    --primary-deep: #5165CC;
    --primary-muted: rgba(114,137,238,.16);
    --primary-subtle: rgba(114,137,238,.09);
    --primary-glow: rgba(114,137,238,.40);
    --on-primary: #FFFFFF;
    --accent: #44DDD9; /* clinical teal — secondary brand */
    --accent-bright: #77EEE9;
    --accent-muted: rgba(68,221,217,.15);
    --accent-subtle: rgba(68,221,217,.08);
    --violet: #C59AFA;
    --violet-muted: rgba(197,154,250,.16);
    --rose: #F990C4;
    --rose-muted: rgba(249,144,196,.15);
    /* ── 2.6  SEMANTIC  (L band .736-.800 — nothing shouts) ─────────────── */
    --success: #50D492;
    --success-muted: rgba(80,212,146,.16);
    --success-subtle: rgba(80,212,146,.09);
    --warning: #F2B036;
    --warning-muted: rgba(242,176,54,.16);
    --warning-subtle: rgba(242,176,54,.09);
    --danger: #FF7B7B;
    --danger-muted: rgba(255,123,123,.16);
    --danger-subtle: rgba(255,123,123,.09);
    --info: #37C6FF;
    --info-muted: rgba(55,198,255,.16);
    --info-subtle: rgba(55,198,255,.09);
    /* ── 2.7  THE AURORA  (levelled to L=.790 — no band mid-sweep) ──────── */
    --aurora-1: #2DD4D0;
    --aurora-2: #56C8FE;
    --aurora-3: #9EB5FF;
    --aurora-4: #CCA5FD;
    --aurora-5: #F897C6;
    --aurora: linear-gradient(115deg, #2DD4D0 0%, #56C8FE 26%, #9EB5FF 52%, #CCA5FD 76%, #F897C6 100%);
    --aurora-rev: linear-gradient(295deg, #2DD4D0 0%, #56C8FE 26%, #9EB5FF 52%, #CCA5FD 76%, #F897C6 100%);
    --aurora-band: linear-gradient(90deg, #2DD4D0, #56C8FE, #9EB5FF, #CCA5FD, #F897C6);
    /* ── 2.8  SHADOWS ──────────────────────────────────────────────────── */
    --shadow-xs: 0 1px 2px rgba(0,0,0,.48);
    --shadow-sm: 0 2px 6px rgba(0,0,0,.42), 0 6px 16px rgba(0,0,0,.32);
    --shadow-md: 0 4px 12px rgba(0,0,0,.44), 0 14px 34px rgba(0,0,0,.40);
    --shadow-lg: 0 10px 24px rgba(0,0,0,.48), 0 28px 64px rgba(0,0,0,.50);
    --shadow-xl: 0 18px 40px rgba(0,0,0,.54), 0 44px 100px rgba(0,0,0,.60);
    /* Chromatic ambient — this is what replaces the old gloss on primary. */
    --shadow-primary: 0 6px 16px -6px var(--primary-glow);
    --shadow-primary-lg: 0 12px 28px -8px var(--primary-glow);
    --highlight-top: inset 0 1px 0 rgba(255,255,255,.06);
    --highlight-top-strong: inset 0 1px 0 rgba(255,255,255,.12);
    /* ── 2.9  FOCUS ────────────────────────────────────────────────────── */
    --ring: 0 0 0 2px var(--bg-base), 0 0 0 4px rgba(114,137,238,.72);
    --ring-danger: 0 0 0 2px var(--bg-base), 0 0 0 4px rgba(255,123,123,.72);
    --ring-soft: 0 0 0 3px rgba(114,137,238,.20);
    /* ── 2.10  INTERACTION ─────────────────────────────────────────────── */
    --hover-bg: rgba(142,160,255,.06);
    --hover-bg-strong: rgba(142,160,255,.11);
    --active-bg: rgba(142,160,255,.17);
    /* ── 2.11  BUTTONS ─────────────────────────────────────────────────────
       Deliberately FLAT. The app sheet ramped #888DFF -> #6D72EF (dL .079),
       which is the single loudest "dated" signal in the old kit. Presence now
       comes from a deep saturated fill + chromatic ambient shadow, the way
       Linear and Stripe do it. White text clears AA on the rest fill. */
    --btn-primary: #576BD1;
    --btn-primary-hover: #6278DF;
    --btn-primary-active: #4A5CC1;
    --btn-neutral: #262B34;
    --btn-neutral-hover: #31353F;
    --btn-neutral-active: #1E222B;
    --btn-neutral-border: rgba(172,184,230,.16);
    --btn-invert: #F2F4F9;
    --btn-invert-hover: #FFFFFF;
    --btn-invert-active: #DDE1EA;
    --btn-invert-text: #0B0E17;
    /* ── 2.12  FIELDS  (opaque on purpose — glass hurts legibility) ─────── */
    --field-bg: #10141D;
    --field-bg-hover: #141924;
    --field-bg-disabled: #12151C;
    --field-border: rgba(158,170,215,.15);
    --field-border-hover: rgba(164,176,222,.26);
    --field-border-focus: var(--primary);
    --field-text: var(--text-primary);
    --field-placeholder: var(--text-faint);
    --field-radius: var(--radius-md);
    --field-h: 42px; /* patient-scale: bigger tap target than the app's 38 */
    --field-h-sm: 34px;
    --field-h-lg: 50px;
    --select-option-bg: #131821;
    /* ── 2.13  CONTAINERS ──────────────────────────────────────────────── */
    --panel-bg: var(--glass-panel);
    --panel-bg-hover: var(--glass-panel-hover);
    --panel-border: var(--glass-edge);
    --panel-border-hover: var(--glass-edge-strong);
    --panel-radius: var(--radius-xl);
    --panel-shadow: var(--shadow-lg);
    --card-bg: var(--glass-card);
    --card-radius: var(--radius-lg);
    --bar-bg: var(--glass-panel);
    --bar-radius: var(--radius-xl);
    /* ── 2.14  OVERLAYS ────────────────────────────────────────────────── */
    --modal-overlay: rgba(2,3,8,.74);
    --modal-bg: var(--glass-modal);
    --modal-border: var(--glass-edge-strong);
    --modal-radius: var(--radius-2xl);
    --modal-shadow: var(--shadow-xl), inset 0 1px 0 rgba(255,255,255,.10);
    --modal-sticky-bg: #1F242E;
    --drawer-overlay: rgba(2,3,8,.68);
    --drawer-bg: #131821;
    --drawer-raised: #212630;
    --drawer-width: min(93vw, 480px);
    --menu-bg: var(--glass-raised);
    --menu-border: var(--glass-edge-strong);
    --menu-radius: var(--radius-lg);
    --tooltip-bg: #373D47;
    --toast-bg: var(--glass-raised);
    --note-bg: var(--glass-note);
    /* ── 2.15  TABLE ───────────────────────────────────────────────────── */
    --table-head-bg: var(--surface-2);
    --table-head-text: var(--text-muted);
    --table-row-alt: rgba(142,160,255,.03);
    --table-row-hover: var(--hover-bg);
    --table-border: var(--border-subtle);
    /* ── 2.16  SMALL PARTS ─────────────────────────────────────────────── */
    --pill-bg: var(--surface-1);
    --chip-bg: var(--surface-1);
    --seg-bg: var(--surface-1);
    --seg-thumb: var(--surface-4);
    --switch-off: #2E3440;
    --switch-on: var(--primary);
    --switch-thumb: #F2F4F9;
    --scroll-thumb: rgba(155,168,215,.18);
    --scroll-thumb-hover: rgba(164,176,222,.32);
    /* ── 2.17  CHARTS ──────────────────────────────────────────────────── */
    --chart-1: #7289EE;
    --chart-2: #44DDD9;
    --chart-3: #50D492;
    --chart-4: #C59AFA;
    --chart-5: #F2B036;
    --chart-6: #F990C4;
    --chart-7: #8B93A3;
    --chart-grid: rgba(155,168,215,.08);
    --chart-axis: rgba(164,176,215,.55);
    --chart-track: rgba(155,168,215,.12);
    --chart-area-from: rgba(114,137,238,.42);
    --chart-area-to: rgba(114,137,238,0);
}


/* ============================================================================
   3.  RESET  &  BASE
   ============================================================================ */
*, *::before, *::after {
    box-sizing: border-box;
}

/* The hidden attribute must always win. Components in this kit set explicit
   display values (.qbtn is inline-flex, .q-pill is inline-flex, …), and an
   explicit display beats the UA's [hidden] rule — so el.hidden = true on a
   button would silently do nothing without this. */
[hidden] {
    display: none !important;
}

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    margin: 0;
    min-height: 100%;
    font-family: var(--font);
    font-size: var(--font-size-base);
    line-height: var(--lh-base);
    color: var(--text-secondary);
    background-color: var(--bg-base);
    background-image: var(--bg-gradient);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    font-feature-settings: "cv11","ss01";
}

form {
    margin: 0;
}

h1, h2, h3, h4, h5, h6 {
    margin: 0;
    color: var(--text-primary);
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
    letter-spacing: var(--ls-tight);
}

p {
    margin: 0 0 var(--sp-3);
}

    p:last-child {
        margin-bottom: 0;
    }

img, svg, video, canvas {
    display: block;
    max-width: 100%;
}

button, input, select, textarea {
    font: inherit;
    color: inherit;
}

hr {
    height: 1px;
    margin: var(--sp-5) 0;
    border: 0;
    background: var(--border-subtle);
}

/* Numerals line up in every table, receipt and result readout. */
.q-num, table, .q-mono, input[type="number"], time, [data-num] {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

.q-mono {
    font-family: var(--font-mono);
    letter-spacing: -.01em;
}

/* Keyboard-only focus, everywhere, one ring. */
:focus {
    outline: none;
}

:focus-visible {
    outline: none;
    box-shadow: var(--ring);
    border-radius: var(--radius-xs);
}

::selection {
    background: rgba(114,137,238,.32);
    color: var(--text-primary);
}

/* Native option lists ignore transparency — give them a solid. */
option {
    background: var(--select-option-bg);
    color: var(--text-primary);
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}


/* ============================================================================
   4.  TYPOGRAPHY HELPERS   (atoms any page can drop in)
   ============================================================================ */
.q-display {
    font-size: var(--font-size-display);
    font-weight: var(--fw-black);
    letter-spacing: -.03em;
    line-height: 1.02;
    color: var(--text-primary);
}

.q-h1 {
    font-size: var(--font-size-xxl);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-tight);
    color: var(--text-primary);
}

.q-h2 {
    font-size: var(--font-size-xl);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-tight);
    color: var(--text-primary);
}

.q-h3 {
    font-size: var(--font-size-lg);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--ls-snug);
    color: var(--text-primary);
}

.q-body {
    font-size: var(--font-size-base);
    line-height: var(--lh-base);
    color: var(--text-secondary);
}

.q-small {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}

.q-tiny {
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-micro {
    font-size: var(--font-size-xxs);
    color: var(--text-faint);
}

/* Eyebrow / kicker — the label above a section title. */
.q-kicker {
    display: block;
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--primary-bright);
}

.q-lead {
    font-size: var(--font-size-lg);
    line-height: 1.55;
    color: var(--text-secondary);
}

.q-muted {
    color: var(--text-muted);
}

.q-faint {
    color: var(--text-faint);
}

.q-strong {
    color: var(--text-primary);
    font-weight: var(--fw-semibold);
}

.q-caps {
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-bold);
}

.q-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.q-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.q-clamp-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Aurora text. Hero numerals only — one per screen, at most. */
.q-grad {
    background: var(--aurora);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}


/* ============================================================================
   5.  BUTTON SYSTEM   (.qbtn)
   ----------------------------------------------------------------------------
   WHAT CHANGED, AND WHY

   The previous kit built its primary as a 180deg gradient (#888DFF -> #6D72EF,
   a 0.079 lightness drop), wrapped it in a contrasting #5F64E6 border, and
   swept a white gloss across it on hover. Those three things together are the
   visual signature of about 2012. Individually they're defensible; stacked,
   they read as plastic.

   This system replaces all three:
     1. FLAT FILL. One colour, no ramp. Depth comes from a 1px inset top
        edge-light, not a gradient.
     2. NO CONTRAST BORDER. The border is transparent. A ring around a filled
        button just draws the eye to the seam.
     3. CHROMATIC AMBIENT SHADOW. Instead of gloss ON the button, indigo light
        falls UNDER it (0 6px 16px -6px). That's what makes a button look like
        it's sitting on the page rather than pasted onto it.
     4. DEEPER FILL. #576BD1 rather than #888DFF. Deep + saturated reads
        expensive; mid + bright reads like a default framework. It also means
        white label text clears WCAG AA (4.74:1) — the old fill did not.

   API
     Base ...... .qbtn
     Variants .. --primary --invert --secondary --ghost --subtle --outline
                 --danger --success --warning --info --link
     Modifier .. --solid   (fills a semantic variant instead of tinting it)
     Sizes ..... --xs --sm  (default md)  --lg --xl
     Shapes .... --pill --block --square --icon
     States .... :hover :active :focus-visible [disabled] .is-active .is-loading
     Parts ..... .qbtn__ico  .qbtn__label  .qbtn__badge
     Groups .... .qbtn-group  .qbtn-segmented
   ============================================================================ */

.qbtn {
    --qbtn-h: 42px;
    --qbtn-px: 18px;
    --qbtn-gap: 8px;
    --qbtn-fs: var(--font-size-sm);
    --qbtn-fw: var(--fw-semibold);
    --qbtn-radius: var(--radius-md);
    --qbtn-ico: 17px;
    --qbtn-lift: -1px;
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--qbtn-gap);
    height: var(--qbtn-h);
    padding: 0 var(--qbtn-px);
    border: 1px solid transparent;
    border-radius: var(--qbtn-radius);
    background: transparent;
    color: var(--text-primary);
    font-family: var(--font);
    font-size: var(--qbtn-fs);
    font-weight: var(--qbtn-fw);
    letter-spacing: -.008em;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform var(--timing-fast) var(--ease-out), background-color var(--timing-fast) var(--ease), border-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease), opacity var(--timing-fast) var(--ease);
}

    .qbtn:focus-visible {
        outline: none;
        box-shadow: var(--ring);
    }

/* --- Parts --- */
.qbtn__ico {
    width: var(--qbtn-ico);
    height: var(--qbtn-ico);
    flex: 0 0 auto;
    pointer-events: none;
}

    .qbtn__ico svg {
        width: 100%;
        height: 100%;
        display: block;
    }

.qbtn__label {
    display: inline-block;
}

.qbtn__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 19px;
    height: 19px;
    padding: 0 6px;
    margin-left: 2px;
    border-radius: var(--radius-pill);
    background: rgba(255,255,255,.16);
    color: inherit;
    font-family: var(--font-mono);
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-semibold);
    line-height: 1;
    letter-spacing: 0;
}

/* --- Sizes --- */
.qbtn--xs {
    --qbtn-h: 30px;
    --qbtn-px: 11px;
    --qbtn-gap: 6px;
    --qbtn-fs: var(--font-size-xxs);
    --qbtn-ico: 14px;
    --qbtn-radius: var(--radius-xs);
}

.qbtn--sm {
    --qbtn-h: 36px;
    --qbtn-px: 14px;
    --qbtn-gap: 7px;
    --qbtn-fs: var(--font-size-xs);
    --qbtn-ico: 15px;
    --qbtn-radius: var(--radius-sm);
}

.qbtn--lg {
    --qbtn-h: 50px;
    --qbtn-px: 24px;
    --qbtn-gap: 10px;
    --qbtn-fs: var(--font-size-base);
    --qbtn-ico: 19px;
    --qbtn-radius: var(--radius-lg);
}

.qbtn--xl {
    --qbtn-h: 58px;
    --qbtn-px: 30px;
    --qbtn-gap: 11px;
    --qbtn-fs: var(--font-size-lg);
    --qbtn-ico: 21px;
    --qbtn-radius: var(--radius-lg);
}

/* --- Shapes --- */
.qbtn--block {
    display: flex;
    width: 100%;
}

.qbtn--pill {
    --qbtn-radius: var(--radius-pill);
}

.qbtn--square, .qbtn--icon {
    width: var(--qbtn-h);
    padding: 0;
    --qbtn-gap: 0;
}


/* === PRIMARY  ·  flat indigo + chromatic ambient. The house CTA. ========== */
.qbtn--primary {
    background-color: var(--btn-primary);
    color: var(--on-primary);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.14), 0 1px 2px rgba(0,0,0,.34), var(--shadow-primary);
}

    .qbtn--primary:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: var(--btn-primary-hover);
        box-shadow: inset 0 1px 0 rgba(255,255,255,.18), 0 2px 4px rgba(0,0,0,.32), var(--shadow-primary-lg);
    }

    .qbtn--primary:active {
        transform: translateY(0);
        background-color: var(--btn-primary-active);
        box-shadow: inset 0 1px 3px rgba(0,0,0,.30);
    }

/* === INVERT  ·  near-white on dark. Reserve for the one decisive action
       on a screen (Pay now, Join visit, Confirm). ========================== */
.qbtn--invert {
    background-color: var(--btn-invert);
    color: var(--btn-invert-text);
    font-weight: var(--fw-bold);
    box-shadow: inset 0 -1px 0 rgba(0,0,0,.10), 0 1px 2px rgba(0,0,0,.38), 0 8px 20px -8px rgba(255,255,255,.22);
}

    .qbtn--invert:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: var(--btn-invert-hover);
        box-shadow: inset 0 -1px 0 rgba(0,0,0,.10), 0 2px 5px rgba(0,0,0,.38), 0 14px 32px -10px rgba(255,255,255,.30);
    }

    .qbtn--invert:active {
        transform: translateY(0);
        background-color: var(--btn-invert-active);
        box-shadow: inset 0 1px 3px rgba(0,0,0,.18);
    }

/* === SECONDARY  ·  raised gunmetal. The default neutral. ================= */
.qbtn--secondary {
    border-color: var(--btn-neutral-border);
    background-color: var(--btn-neutral);
    color: var(--text-primary);
    box-shadow: var(--highlight-top), 0 1px 2px rgba(0,0,0,.36);
}

    .qbtn--secondary:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: var(--btn-neutral-hover);
        border-color: var(--border-strong);
        box-shadow: var(--highlight-top-strong), 0 2px 4px rgba(0,0,0,.34), var(--shadow-sm);
    }

    .qbtn--secondary:active {
        transform: translateY(0);
        background-color: var(--btn-neutral-active);
        box-shadow: inset 0 1px 3px rgba(0,0,0,.30);
    }

/* === OUTLINE  ·  hairline only. For dense toolbars. ====================== */
.qbtn--outline {
    border-color: var(--border-strong);
    background-color: transparent;
    color: var(--text-secondary);
}

    .qbtn--outline:hover {
        border-color: var(--border-interactive);
        background-color: var(--hover-bg);
        color: var(--text-primary);
    }

    .qbtn--outline:active {
        background-color: var(--active-bg);
    }

/* === GHOST  ·  no chrome at rest. ======================================== */
.qbtn--ghost {
    background-color: transparent;
    color: var(--text-secondary);
}

    .qbtn--ghost:hover {
        background-color: var(--hover-bg-strong);
        color: var(--text-primary);
    }

    .qbtn--ghost:active {
        background-color: var(--active-bg);
    }

/* === SUBTLE  ·  tinted indigo. Secondary actions near a primary. ========= */
.qbtn--subtle {
    background-color: var(--primary-muted);
    color: var(--primary-bright);
}

    .qbtn--subtle:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: rgba(114,137,238,.24);
    }

    .qbtn--subtle:active {
        transform: translateY(0);
        background-color: var(--primary-muted);
    }

/* === LINK ================================================================ */
.qbtn--link {
    height: auto;
    padding: 0;
    border: none;
    background: none;
    color: var(--primary-bright);
    box-shadow: none;
}

    .qbtn--link:hover {
        color: var(--accent-bright);
        text-decoration: underline;
        text-underline-offset: 3px;
    }

    .qbtn--link:active {
        opacity: .82;
    }

/* === SEMANTIC  ·  tinted by default; add --solid to fill ================= */
.qbtn--danger {
    background-color: var(--danger-muted);
    color: var(--danger);
}

    .qbtn--danger:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: rgba(255,123,123,.24);
    }

    .qbtn--danger:active {
        transform: translateY(0);
        background-color: var(--danger-muted);
    }

    .qbtn--danger:focus-visible {
        box-shadow: var(--ring-danger);
    }

.qbtn--success {
    background-color: var(--success-muted);
    color: var(--success);
}

    .qbtn--success:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: rgba(80,212,146,.24);
    }

    .qbtn--success:active {
        transform: translateY(0);
        background-color: var(--success-muted);
    }

.qbtn--warning {
    background-color: var(--warning-muted);
    color: var(--warning);
}

    .qbtn--warning:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: rgba(242,176,54,.24);
    }

    .qbtn--warning:active {
        transform: translateY(0);
        background-color: var(--warning-muted);
    }

.qbtn--info {
    background-color: var(--info-muted);
    color: var(--info);
}

    .qbtn--info:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: rgba(55,198,255,.24);
    }

    .qbtn--info:active {
        transform: translateY(0);
        background-color: var(--info-muted);
    }

/* --solid: fill the semantic. Dark ink on the light fills is deliberate —
   these colours are too light to carry white text at AA. */
.qbtn--danger.qbtn--solid {
    background-color: var(--danger);
    color: var(--text-on-light);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 1px 2px rgba(0,0,0,.34), 0 6px 16px -6px rgba(255,123,123,.40);
}

    .qbtn--danger.qbtn--solid:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: #FF9090;
    }

.qbtn--success.qbtn--solid {
    background-color: var(--success);
    color: var(--text-on-light);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 1px 2px rgba(0,0,0,.34), 0 6px 16px -6px rgba(80,212,146,.40);
}

    .qbtn--success.qbtn--solid:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: #64DDA0;
    }

.qbtn--warning.qbtn--solid {
    background-color: var(--warning);
    color: var(--text-on-light);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 1px 2px rgba(0,0,0,.34), 0 6px 16px -6px rgba(242,176,54,.40);
}

    .qbtn--warning.qbtn--solid:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: #F7BC50;
    }

.qbtn--info.qbtn--solid {
    background-color: var(--info);
    color: var(--text-on-light);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 1px 2px rgba(0,0,0,.34), 0 6px 16px -6px rgba(55,198,255,.40);
}

    .qbtn--info.qbtn--solid:hover {
        transform: translateY(var(--qbtn-lift));
        background-color: #55CEFF;
    }

/* === AURORA  ·  the one showpiece button. Onboarding, upgrade, first-run.
       Never more than one per screen; ideally not more than one per session. */
.qbtn--aurora {
    position: relative;
    border: 0;
    background: var(--aurora);
    background-size: 200% 100%;
    background-position: 0% 50%;
    color: var(--text-on-light);
    font-weight: var(--fw-bold);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.30), 0 1px 2px rgba(0,0,0,.34), 0 10px 26px -10px rgba(114,137,238,.55);
    transition: background-position var(--timing-slow) var(--ease), transform var(--timing-fast) var(--ease-out), box-shadow var(--timing-fast) var(--ease);
}

    .qbtn--aurora:hover {
        transform: translateY(var(--qbtn-lift));
        background-position: 100% 50%;
        box-shadow: inset 0 1px 0 rgba(255,255,255,.36), 0 2px 5px rgba(0,0,0,.32), 0 16px 34px -12px rgba(114,137,238,.62);
    }

    .qbtn--aurora:active {
        transform: translateY(0);
    }

/* === ICON BUTTON  ·  standalone square, neutral by default =============== */
.qbtn-ico {
    display: inline-grid;
    place-items: center;
    width: 38px;
    height: 38px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease), border-color var(--timing-fast) var(--ease), transform var(--timing-fast) var(--ease-out);
}

    .qbtn-ico svg {
        width: 18px;
        height: 18px;
    }

    .qbtn-ico:hover {
        background: var(--hover-bg-strong);
        color: var(--text-primary);
    }

    .qbtn-ico:active {
        transform: scale(.94);
        background: var(--active-bg);
    }

    .qbtn-ico:focus-visible {
        outline: none;
        box-shadow: var(--ring);
    }

    .qbtn-ico.is-active {
        background: var(--primary-muted);
        color: var(--primary-bright);
    }

.qbtn-ico--sm {
    width: 32px;
    height: 32px;
}

    .qbtn-ico--sm svg {
        width: 16px;
        height: 16px;
    }

.qbtn-ico--lg {
    width: 44px;
    height: 44px;
}

    .qbtn-ico--lg svg {
        width: 20px;
        height: 20px;
    }

.qbtn-ico--pill {
    border-radius: var(--radius-pill);
}

.qbtn-ico--danger:hover {
    background: var(--danger-muted);
    color: var(--danger);
}

/* === STATES ============================================================== */
.qbtn[disabled], .qbtn.is-disabled, .qbtn-ico[disabled] {
    pointer-events: none;
    opacity: .42;
    transform: none !important;
    box-shadow: none !important;
    filter: saturate(.6);
}

.qbtn.is-active {
    background-color: var(--primary-muted);
    color: var(--primary-bright);
}

/* Loading: label fades, a ring spins in the middle. Width never jumps. */
.qbtn.is-loading {
    pointer-events: none;
    color: transparent !important;
}

    .qbtn.is-loading > * {
        opacity: 0;
    }

    .qbtn.is-loading::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: 16px;
        height: 16px;
        margin: -8px 0 0 -8px;
        border: 2px solid currentColor;
        border-radius: 50%;
        border-top-color: transparent;
        opacity: .9;
        color: var(--text-primary);
        animation: q-spin .62s linear infinite;
    }

.qbtn--primary.is-loading::after, .qbtn--aurora.is-loading::after {
    color: #fff;
}

.qbtn--invert.is-loading::after {
    color: var(--btn-invert-text);
}

@keyframes q-spin {
    to {
        transform: rotate(360deg);
    }
}

/* === GROUPS ============================================================== */
.qbtn-group {
    display: inline-flex;
    align-items: center;
}

    .qbtn-group .qbtn {
        --qbtn-radius: 0;
        margin-left: -1px;
    }

        .qbtn-group .qbtn:first-child {
            border-top-left-radius: var(--radius-md);
            border-bottom-left-radius: var(--radius-md);
            margin-left: 0;
        }

        .qbtn-group .qbtn:last-child {
            border-top-right-radius: var(--radius-md);
            border-bottom-right-radius: var(--radius-md);
        }

        .qbtn-group .qbtn:hover, .qbtn-group .qbtn:focus-visible {
            z-index: 1;
            transform: none;
        }

/* Segmented control — a single-choice switch, not a group of buttons. */
.qbtn-segmented {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--seg-bg);
}

    .qbtn-segmented .qbtn {
        --qbtn-h: 32px;
        --qbtn-px: 15px;
        --qbtn-fs: var(--font-size-xs);
        --qbtn-radius: var(--radius-xs);
        color: var(--text-muted);
        background: transparent;
        border-color: transparent;
        box-shadow: none;
    }

        .qbtn-segmented .qbtn:hover {
            transform: none;
            color: var(--text-primary);
            background: var(--hover-bg);
            box-shadow: none;
        }

        .qbtn-segmented .qbtn.is-active {
            color: var(--text-primary);
            background: var(--seg-thumb);
            box-shadow: var(--highlight-top), 0 1px 2px rgba(0,0,0,.32);
        }

/* Action bar — the row that ends a form or a modal. Primary sits right. */
.qbtn-bar {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
}

.qbtn-bar--end {
    justify-content: flex-end;
}

.qbtn-bar--split {
    justify-content: space-between;
}

/* On phones, stack a form's action bar and let the primary go full width —
   thumb reach matters more than symmetry. */
@media (max-width: 560px) {
    .qbtn-bar--stack {
        flex-direction: column-reverse;
        align-items: stretch;
    }

        .qbtn-bar--stack .qbtn {
            width: 100%;
        }
}


/* ============================================================================
   6.  FORM CONTROLS
   ----------------------------------------------------------------------------
   Fields stay OPAQUE while panels are glass. Frosted input backgrounds look
   lovely in a screenshot and cost real legibility when someone is typing an
   insurance number on a bus. Controls are 42px (50px on the --lg step), which
   clears the 44px touch guidance once padding is counted.

   API
     .q-field            wrapper (label + control + hint/error)
     .q-label            label      .q-label__req  for the asterisk
     .q-hint  .q-error   helper text under a control
     .q-input            text input / textarea
     .q-select           native select with a themed chevron
     .q-inputgroup       control with a leading icon or an affix
     .q-radio .q-check   custom radio / checkbox
     .q-switch           animated toggle
   ============================================================================ */

/* --- Label / hint / error --- */
.q-label {
    display: block;
    margin-bottom: var(--sp-2);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .01em;
    color: var(--text-secondary);
}

.q-label__req {
    margin-left: 3px;
    color: var(--danger);
}

.q-label__opt {
    margin-left: 6px;
    font-weight: var(--fw-regular);
    color: var(--text-faint);
}

.q-hint {
    display: block;
    margin-top: var(--sp-2);
    font-size: var(--font-size-xs);
    line-height: 1.45;
    color: var(--text-muted);
}

.q-error {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: var(--sp-2);
    font-size: var(--font-size-xs);
    line-height: 1.45;
    color: var(--danger);
}

    .q-error svg {
        width: 14px;
        height: 14px;
        flex: 0 0 auto;
        margin-top: 1px;
    }

.q-field {
    display: block;
    margin-bottom: var(--sp-5);
}

    .q-field:last-child {
        margin-bottom: 0;
    }

/* --- Text input / textarea --- */
.q-input {
    display: block;
    width: 100%;
    height: var(--field-h);
    padding: 0 14px;
    border: 1px solid var(--field-border);
    border-radius: var(--field-radius);
    background: var(--field-bg);
    color: var(--field-text);
    font-family: var(--font);
    font-size: var(--font-size-base);
    line-height: normal;
    box-shadow: inset 0 1px 2px rgba(0,0,0,.22);
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-input::placeholder {
        color: var(--field-placeholder);
    }

    .q-input:hover:not(:disabled):not(:focus) {
        border-color: var(--field-border-hover);
        background: var(--field-bg-hover);
    }

    .q-input:focus {
        outline: none;
        border-color: var(--field-border-focus);
        background: var(--field-bg-hover);
        box-shadow: inset 0 1px 2px rgba(0,0,0,.20), var(--ring-soft);
    }

    .q-input:disabled {
        background: var(--field-bg-disabled);
        color: var(--text-faint);
        cursor: not-allowed;
        box-shadow: none;
    }

    .q-input[readonly] {
        background: var(--surface-1);
        color: var(--text-secondary);
    }

    .q-input.is-error {
        border-color: var(--danger);
    }

        .q-input.is-error:focus {
            box-shadow: inset 0 1px 2px rgba(0,0,0,.20), 0 0 0 3px rgba(255,123,123,.20);
        }

    .q-input.is-success {
        border-color: var(--success);
    }

textarea.q-input {
    height: auto;
    min-height: 108px;
    padding: 11px 14px;
    line-height: var(--lh-base);
    resize: vertical;
}

textarea.q-input--fixed {
    resize: none;
}

textarea.q-input--auto {
    resize: none;
    overflow: hidden;
}

/* --- Field sizes --- */
.q-input--sm {
    height: var(--field-h-sm);
    padding: 0 11px;
    font-size: var(--font-size-sm);
    border-radius: var(--radius-sm);
}

.q-input--lg {
    height: var(--field-h-lg);
    padding: 0 17px;
    font-size: var(--font-size-lg);
    border-radius: var(--radius-lg);
}

/* --- Input group: leading icon and/or affixes --- */
.q-inputgroup {
    position: relative;
    display: flex;
    align-items: center;
}

    .q-inputgroup .q-input {
        flex: 1 1 auto;
    }

.q-inputgroup__ico {
    position: absolute;
    left: 13px;
    width: 17px;
    height: 17px;
    color: var(--text-faint);
    pointer-events: none;
    transition: color var(--timing-fast) var(--ease);
}

    .q-inputgroup__ico ~ .q-input {
        padding-left: 40px;
    }

.q-inputgroup:focus-within .q-inputgroup__ico {
    color: var(--primary);
}

.q-inputgroup__ico--right {
    left: auto;
    right: 13px;
}

    .q-inputgroup__ico--right ~ .q-input {
        padding-right: 40px;
    }

/* Trailing action inside a field (clear, reveal password, copy). */
.q-inputgroup__act {
    position: absolute;
    right: 6px;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--text-faint);
    cursor: pointer;
    transition: color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease);
}

    .q-inputgroup__act svg {
        width: 16px;
        height: 16px;
    }

    .q-inputgroup__act:hover {
        color: var(--text-primary);
        background: var(--hover-bg-strong);
    }

/* Affix: a static unit or prefix glued to the control (CA$, %, /month). */
.q-affix {
    display: inline-flex;
    align-items: center;
    height: var(--field-h);
    padding: 0 13px;
    border: 1px solid var(--field-border);
    background: var(--surface-2);
    color: var(--text-muted);
    font-size: var(--font-size-sm);
    white-space: nowrap;
}

.q-affix--pre {
    border-right: 0;
    border-radius: var(--field-radius) 0 0 var(--field-radius);
}

    .q-affix--pre + .q-input {
        border-radius: 0 var(--field-radius) var(--field-radius) 0;
    }

.q-affix--post {
    border-left: 0;
    border-radius: 0 var(--field-radius) var(--field-radius) 0;
}

.q-input--joinstart {
    border-radius: var(--field-radius) 0 0 var(--field-radius);
}

/* --- Native select with a themed chevron --- */
.q-select {
    display: block;
    width: 100%;
    height: var(--field-h);
    padding: 0 40px 0 14px;
    border: 1px solid var(--field-border);
    border-radius: var(--field-radius);
    background-color: var(--field-bg);
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239EA2AB' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 13px center;
    background-size: 17px;
    color: var(--field-text);
    font-family: var(--font);
    font-size: var(--font-size-base);
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    box-shadow: inset 0 1px 2px rgba(0,0,0,.22);
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-select:hover:not(:disabled):not(:focus) {
        border-color: var(--field-border-hover);
        background-color: var(--field-bg-hover);
    }

    .q-select:focus {
        outline: none;
        border-color: var(--field-border-focus);
        box-shadow: inset 0 1px 2px rgba(0,0,0,.20), var(--ring-soft);
    }

    .q-select:disabled {
        background-color: var(--field-bg-disabled);
        color: var(--text-faint);
        cursor: not-allowed;
    }

    .q-select.is-error {
        border-color: var(--danger);
    }

.q-select--sm {
    height: var(--field-h-sm);
    padding-left: 11px;
    font-size: var(--font-size-sm);
    border-radius: var(--radius-sm);
}

.q-select--lg {
    height: var(--field-h-lg);
    padding-left: 17px;
    font-size: var(--font-size-lg);
    border-radius: var(--radius-lg);
}

/* --- Search --- */
.q-search {
    position: relative;
    display: flex;
    align-items: center;
}

.q-search__ico {
    position: absolute;
    left: 14px;
    width: 17px;
    height: 17px;
    color: var(--text-faint);
    pointer-events: none;
}

.q-search__input {
    width: 100%;
    height: var(--field-h);
    padding: 0 40px 0 42px;
    border: 1px solid var(--field-border);
    border-radius: var(--radius-pill);
    background: var(--field-bg);
    color: var(--field-text);
    font-family: var(--font);
    font-size: var(--font-size-base);
    box-shadow: inset 0 1px 2px rgba(0,0,0,.22);
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-search__input::placeholder {
        color: var(--field-placeholder);
    }

    .q-search__input::-webkit-search-cancel-button {
        -webkit-appearance: none;
        appearance: none;
    }

    .q-search__input:focus {
        outline: none;
        border-color: var(--field-border-focus);
        box-shadow: inset 0 1px 2px rgba(0,0,0,.20), var(--ring-soft);
    }

.q-search:focus-within .q-search__ico {
    color: var(--primary);
}

.q-search__clear {
    position: absolute;
    right: 8px;
    display: none;
    place-items: center;
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 50%;
    background: var(--hover-bg-strong);
    color: var(--text-muted);
    cursor: pointer;
}

    .q-search__clear svg {
        width: 14px;
        height: 14px;
    }

    .q-search__clear:hover {
        color: var(--text-primary);
        background: var(--active-bg);
    }

.q-search.has-value .q-search__clear {
    display: grid;
}

/* === CUSTOM RADIO ======================================================== */
.q-radio {
    position: relative;
    display: inline-flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}

    .q-radio input {
        position: absolute;
        opacity: 0;
        width: 0;
        height: 0;
    }

.q-radio__mark {
    position: relative;
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin-top: 1px;
    border: 1.5px solid var(--border-strong);
    border-radius: 50%;
    background: var(--field-bg);
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-radio__mark::after {
        content: "";
        position: absolute;
        inset: 0;
        margin: auto;
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: #fff;
        transform: scale(0);
        transition: transform var(--timing) var(--ease-spring);
    }

.q-radio__label {
    font-size: var(--font-size-sm);
    line-height: 1.45;
    color: var(--text-secondary);
}

.q-radio__sub {
    display: block;
    margin-top: 2px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-radio:hover .q-radio__mark {
    border-color: var(--border-interactive);
}

.q-radio input:checked ~ .q-radio__mark {
    border-color: var(--primary);
    background: var(--primary);
}

    .q-radio input:checked ~ .q-radio__mark::after {
        transform: scale(1);
    }

.q-radio input:focus-visible ~ .q-radio__mark {
    box-shadow: var(--ring);
}

.q-radio input:disabled ~ .q-radio__mark {
    opacity: .45;
}

.q-radio input:disabled ~ .q-radio__label {
    opacity: .45;
}

.q-radio input:checked ~ .q-radio__label {
    color: var(--text-primary);
}

/* === CUSTOM CHECKBOX ===================================================== */
.q-check {
    position: relative;
    display: inline-flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}

    .q-check input {
        position: absolute;
        opacity: 0;
        width: 0;
        height: 0;
    }

.q-check__mark {
    position: relative;
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin-top: 1px;
    border: 1.5px solid var(--border-strong);
    border-radius: 6px;
    background: var(--field-bg);
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-check__mark::after {
        content: "";
        position: absolute;
        top: 2px;
        left: 6px;
        width: 5px;
        height: 10px;
        border: solid #fff;
        border-width: 0 2px 2px 0;
        transform: rotate(45deg) scale(0);
        transform-origin: center;
        transition: transform var(--timing) var(--ease-spring);
    }

.q-check__label {
    font-size: var(--font-size-sm);
    line-height: 1.45;
    color: var(--text-secondary);
}

.q-check__sub {
    display: block;
    margin-top: 2px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-check:hover .q-check__mark {
    border-color: var(--border-interactive);
}

.q-check input:checked ~ .q-check__mark {
    border-color: var(--primary);
    background: var(--primary);
}

    .q-check input:checked ~ .q-check__mark::after {
        transform: rotate(45deg) scale(1);
    }

.q-check input:indeterminate ~ .q-check__mark {
    border-color: var(--primary);
    background: var(--primary);
}

    .q-check input:indeterminate ~ .q-check__mark::after {
        top: 8px;
        left: 4px;
        width: 10px;
        height: 2px;
        border: 0;
        background: #fff;
        border-radius: 1px;
        transform: none;
    }

.q-check input:focus-visible ~ .q-check__mark {
    box-shadow: var(--ring);
}

.q-check input:disabled ~ .q-check__mark, .q-check input:disabled ~ .q-check__label {
    opacity: .45;
}

.q-check input:checked ~ .q-check__label {
    color: var(--text-primary);
}

/* === SWITCH ============================================================== */
.q-switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 11px;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}

    .q-switch input {
        position: absolute;
        opacity: 0;
        width: 0;
        height: 0;
    }

.q-switch__track {
    position: relative;
    flex: 0 0 auto;
    width: 44px;
    height: 26px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-pill);
    background: var(--switch-off);
    box-shadow: inset 0 1px 3px rgba(0,0,0,.34);
    transition: background-color var(--timing) var(--ease), border-color var(--timing) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-switch__track::after {
        content: "";
        position: absolute;
        top: 2px;
        left: 2px;
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background: var(--switch-thumb);
        box-shadow: 0 1px 3px rgba(0,0,0,.45);
        transition: transform var(--timing) var(--ease-spring);
    }

.q-switch__label {
    font-size: var(--font-size-sm);
    color: var(--text-secondary);
}

.q-switch input:checked ~ .q-switch__track {
    background: var(--switch-on);
    border-color: var(--primary-deep);
}

    .q-switch input:checked ~ .q-switch__track::after {
        transform: translateX(18px);
    }

.q-switch input:focus-visible ~ .q-switch__track {
    box-shadow: var(--ring);
}

.q-switch input:disabled ~ .q-switch__track {
    opacity: .45;
}

.q-switch input:checked ~ .q-switch__label {
    color: var(--text-primary);
}

.q-switch--sm .q-switch__track {
    width: 36px;
    height: 21px;
}

    .q-switch--sm .q-switch__track::after {
        width: 15px;
        height: 15px;
    }

.q-switch--sm input:checked ~ .q-switch__track::after {
    transform: translateX(15px);
}

.q-switch--lg .q-switch__track {
    width: 54px;
    height: 31px;
}

    .q-switch--lg .q-switch__track::after {
        width: 25px;
        height: 25px;
    }

.q-switch--lg input:checked ~ .q-switch__track::after {
    transform: translateX(23px);
}

/* Switch laid out as a settings row: label left, control hard right. */
.q-switch--row {
    display: flex;
    width: 100%;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-4);
}

    .q-switch--row .q-switch__track {
        order: 2;
    }

/* === SELECTABLE CARD  ·  a radio/checkbox rendered as a pickable tile ==== */
.q-pick {
    position: relative;
    display: block;
    cursor: pointer;
}

    .q-pick input {
        position: absolute;
        opacity: 0;
        width: 0;
        height: 0;
    }

.q-pick__body {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease), transform var(--timing-fast) var(--ease-out);
}

.q-pick:hover .q-pick__body {
    border-color: var(--border-strong);
    background: var(--surface-2);
}

.q-pick input:checked ~ .q-pick__body {
    border-color: var(--primary);
    background: var(--primary-subtle);
    box-shadow: var(--ring-soft);
}

.q-pick input:focus-visible ~ .q-pick__body {
    box-shadow: var(--ring);
}

.q-pick input:disabled ~ .q-pick__body {
    opacity: .45;
    cursor: not-allowed;
}

.q-pick__ico {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: var(--radius-sm);
    background: var(--surface-3);
    color: var(--text-muted);
}

    .q-pick__ico svg {
        width: 19px;
        height: 19px;
    }

.q-pick input:checked ~ .q-pick__body .q-pick__ico {
    background: var(--primary-muted);
    color: var(--primary-bright);
}

.q-pick__main {
    flex: 1 1 auto;
    min-width: 0;
}

.q-pick__title {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-pick__sub {
    margin-top: 2px;
    font-size: var(--font-size-xs);
    line-height: 1.45;
    color: var(--text-muted);
}

.q-pick__tick {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    margin-top: 1px;
    border: 1.5px solid var(--border-strong);
    border-radius: 50%;
    color: transparent;
    transition: all var(--timing-fast) var(--ease);
}

    .q-pick__tick svg {
        width: 12px;
        height: 12px;
    }

.q-pick input:checked ~ .q-pick__body .q-pick__tick {
    border-color: var(--primary);
    background: var(--primary);
    color: #fff;
}

/* === NUMBER STEPPER ====================================================== */
.q-stepper {
    display: inline-flex;
    align-items: center;
    height: var(--field-h);
    border: 1px solid var(--field-border);
    border-radius: var(--field-radius);
    background: var(--field-bg);
    overflow: hidden;
}

.q-stepper__btn {
    display: grid;
    place-items: center;
    width: 40px;
    height: 100%;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: background-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease);
}

    .q-stepper__btn svg {
        width: 16px;
        height: 16px;
    }

    .q-stepper__btn:hover {
        background: var(--hover-bg-strong);
        color: var(--text-primary);
    }

    .q-stepper__btn:disabled {
        opacity: .35;
        cursor: not-allowed;
    }

.q-stepper__value {
    width: 54px;
    height: 100%;
    border: 0;
    border-left: 1px solid var(--border-subtle);
    border-right: 1px solid var(--border-subtle);
    background: transparent;
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    text-align: center;
    -moz-appearance: textfield;
    appearance: textfield;
}

    .q-stepper__value::-webkit-outer-spin-button, .q-stepper__value::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }

    .q-stepper__value:focus {
        outline: none;
        background: var(--field-bg-hover);
    }

/* === TAG INPUT =========================================================== */
.q-taginput {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-height: var(--field-h);
    padding: 6px 10px;
    border: 1px solid var(--field-border);
    border-radius: var(--field-radius);
    background: var(--field-bg);
    box-shadow: inset 0 1px 2px rgba(0,0,0,.22);
    cursor: text;
    transition: border-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-taginput:focus-within {
        border-color: var(--field-border-focus);
        box-shadow: inset 0 1px 2px rgba(0,0,0,.20), var(--ring-soft);
    }

.q-taginput__field {
    flex: 1 1 90px;
    min-width: 90px;
    height: 26px;
    border: 0;
    background: transparent;
    color: var(--field-text);
    font-family: var(--font);
    font-size: var(--font-size-sm);
}

    .q-taginput__field:focus {
        outline: none;
    }

    .q-taginput__field::placeholder {
        color: var(--field-placeholder);
    }

.q-tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 26px;
    padding: 0 6px 0 10px;
    border-radius: var(--radius-xs);
    background: var(--primary-muted);
    color: var(--primary-bright);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-medium);
}

.q-tag__x {
    display: grid;
    place-items: center;
    width: 16px;
    height: 16px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    opacity: .7;
}

    .q-tag__x svg {
        width: 11px;
        height: 11px;
    }

    .q-tag__x:hover {
        opacity: 1;
        background: rgba(255,255,255,.12);
    }

/* === FIELD LAYOUT HELPERS =============================================== */
.q-formgrid {
    display: grid;
    gap: var(--sp-5);
    grid-template-columns: repeat(12, minmax(0, 1fr));
}

    .q-formgrid > .q-field {
        grid-column: span 12;
        margin-bottom: 0;
    }

.q-col-6 {
    grid-column: span 6 !important;
}

.q-col-4 {
    grid-column: span 4 !important;
}

.q-col-3 {
    grid-column: span 3 !important;
}

.q-col-8 {
    grid-column: span 8 !important;
}

@media (max-width: 700px) {
    .q-formgrid > .q-field, .q-col-6, .q-col-4, .q-col-3, .q-col-8 {
        grid-column: span 12 !important;
    }
}

.q-fieldset {
    border: 0;
    padding: 0;
    margin: 0 0 var(--sp-6);
}

.q-fieldset__legend {
    padding: 0;
    margin-bottom: var(--sp-4);
    font-size: var(--font-size-lg);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

/* Autofill: Chrome paints its own yellow. Repaint it with an inset shadow. */
.q-input:-webkit-autofill, .q-select:-webkit-autofill, .q-search__input:-webkit-autofill {
    -webkit-text-fill-color: var(--text-primary);
    -webkit-box-shadow: 0 0 0 1000px var(--field-bg) inset;
    caret-color: var(--text-primary);
    transition: background-color 5000s ease-in-out 0s;
}


/* ============================================================================
   7.  CONTAINERS   ·   PANELS / CARDS / BARS
   ----------------------------------------------------------------------------
   Panels are glass: they refract the bloomed canvas behind them, which is what
   makes the portal feel like it has depth rather than layers of flat grey.
   That only works if the body stays opaque and bloomed — see section 3.
   Cards are a lighter step that sit INSIDE panels. Wells are recessed.
   ============================================================================ */
.q-panel {
    position: relative;
    border: 1px solid var(--panel-border);
    border-radius: var(--panel-radius);
    background: var(--panel-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--highlight-top), var(--panel-shadow);
}

.q-panel--pad {
    padding: var(--sp-6);
}

.q-panel--tight {
    padding: var(--sp-4);
}

.q-panel--flat {
    box-shadow: var(--highlight-top);
}

.q-panel--solid {
    background: var(--surface-3);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

.q-panel--hover {
    transition: background-color var(--timing) var(--ease), border-color var(--timing) var(--ease), transform var(--timing) var(--ease-out), box-shadow var(--timing) var(--ease);
}

    .q-panel--hover:hover {
        transform: translateY(-2px);
        border-color: var(--panel-border-hover);
        background: var(--panel-bg-hover);
        box-shadow: var(--highlight-top-strong), var(--shadow-xl);
    }

/* The asymmetric-radius signature, inherited from the portal. Opt in. */
.q-asym {
    border-radius: var(--radius-asym-lg);
}

/* Focal panel: an aurora hairline along the top edge. This is the system's
   signature moment — use it on the ONE panel that matters on a screen. */
.q-panel--focal::before {
    content: "";
    position: absolute;
    top: 0;
    left: 18px;
    right: 18px;
    height: 1px;
    background: var(--aurora-band);
    opacity: .85;
    border-radius: 1px;
}

.q-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-5) var(--sp-6);
    border-bottom: 1px solid var(--panel-border);
}

.q-panel__title {
    font-size: var(--font-size-lg);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--ls-snug);
    color: var(--text-primary);
}

.q-panel__sub {
    margin-top: 2px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-panel__actions {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex: 0 0 auto;
}

.q-panel__body {
    padding: var(--sp-6);
}

.q-panel__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-6);
    border-top: 1px solid var(--panel-border);
}

/* Card — a lighter sub-container that sits on a panel. */
.q-card {
    border: 1px solid var(--border-subtle);
    border-radius: var(--card-radius);
    background: var(--card-bg);
    padding: var(--sp-5);
}

.q-card--hover {
    transition: background-color var(--timing) var(--ease), border-color var(--timing) var(--ease), transform var(--timing) var(--ease-out);
    cursor: pointer;
}

    .q-card--hover:hover {
        transform: translateY(-2px);
        border-color: var(--border-default);
        background: var(--surface-4);
    }

/* Well — recessed. For read-only summaries, quoted content, totals. */
.q-well {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-0);
    padding: var(--sp-4);
    box-shadow: inset 0 1px 3px rgba(0,0,0,.28);
}

/* Bar — a horizontal strip: filters, toolbars, sticky summaries. */
.q-bar {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--panel-border);
    border-radius: var(--bar-radius);
    background: var(--bar-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--highlight-top), var(--shadow-sm);
}

.q-bar__spacer {
    flex: 1 1 auto;
}

/* Divider */
.q-divider {
    height: 1px;
    border: 0;
    margin: var(--sp-5) 0;
    background: var(--border-subtle);
}

.q-divider--v {
    width: 1px;
    height: 22px;
    margin: 0 var(--sp-2);
    background: var(--border-default);
}

/* Labelled divider:  ──── or ──── */
.q-divider-label {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin: var(--sp-5) 0;
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-faint);
}

    .q-divider-label::before, .q-divider-label::after {
        content: "";
        flex: 1 1 auto;
        height: 1px;
        background: var(--border-subtle);
    }


/* ============================================================================
   8.  PILLS / CHIPS / BADGES / STATUS
   ----------------------------------------------------------------------------
   PILL   = a status readout. Not clickable.
   CHIP   = a removable or toggleable filter. Clickable.
   BADGE  = a count.
   DOT    = the smallest possible status signal, for lists.
   ============================================================================ */
.q-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 25px;
    padding: 0 11px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    background: var(--pill-bg);
    color: var(--text-secondary);
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-semibold);
    line-height: 1;
    white-space: nowrap;
}

    .q-pill svg {
        width: 13px;
        height: 13px;
    }

.q-pill--sm {
    height: 21px;
    padding: 0 8px;
    font-size: 11px;
}

.q-pill--lg {
    height: 30px;
    padding: 0 14px;
    font-size: var(--font-size-xs);
}

.q-pill--primary {
    border-color: rgba(114,137,238,.26);
    background: var(--primary-muted);
    color: var(--primary-bright);
}

.q-pill--success {
    border-color: rgba(80,212,146,.26);
    background: var(--success-muted);
    color: var(--success);
}

.q-pill--warning {
    border-color: rgba(242,176,54,.26);
    background: var(--warning-muted);
    color: var(--warning);
}

.q-pill--danger {
    border-color: rgba(255,123,123,.26);
    background: var(--danger-muted);
    color: var(--danger);
}

.q-pill--info {
    border-color: rgba(55,198,255,.26);
    background: var(--info-muted);
    color: var(--info);
}

.q-pill--accent {
    border-color: rgba(68,221,217,.26);
    background: var(--accent-muted);
    color: var(--accent);
}

.q-pill--violet {
    border-color: rgba(197,154,250,.26);
    background: var(--violet-muted);
    color: var(--violet);
}

.q-pill--outline {
    background: transparent;
    border-color: var(--border-strong);
    color: var(--text-muted);
}

/* Chip — interactive filter. */
.q-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 32px;
    padding: 0 13px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-pill);
    background: var(--chip-bg);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-medium);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--timing-fast) var(--ease), border-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease);
}

    .q-chip svg {
        width: 14px;
        height: 14px;
    }

    .q-chip:hover {
        border-color: var(--border-strong);
        background: var(--surface-2);
        color: var(--text-primary);
    }

    .q-chip.is-active {
        border-color: var(--primary);
        background: var(--primary-muted);
        color: var(--primary-bright);
    }

    .q-chip:focus-visible {
        outline: none;
        box-shadow: var(--ring);
    }

.q-chip__x {
    display: grid;
    place-items: center;
    width: 17px;
    height: 17px;
    margin-right: -4px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    opacity: .65;
    cursor: pointer;
}

    .q-chip__x svg {
        width: 11px;
        height: 11px;
    }

    .q-chip__x:hover {
        opacity: 1;
        background: rgba(255,255,255,.12);
    }

/* Badge — a count. */
.q-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: var(--radius-pill);
    background: var(--primary);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: var(--fw-semibold);
    line-height: 1;
}

.q-badge--danger {
    background: var(--danger);
    color: var(--text-on-light);
}

.q-badge--success {
    background: var(--success);
    color: var(--text-on-light);
}

.q-badge--neutral {
    background: var(--surface-4);
    color: var(--text-secondary);
}

.q-badge--dot {
    min-width: 8px;
    width: 8px;
    height: 8px;
    padding: 0;
}

/* Status dot + label — the densest readout in the kit. */
.q-status {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: var(--font-size-xs);
    color: var(--text-secondary);
}

.q-status__dot {
    width: 7px;
    height: 7px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--text-faint);
}

.q-status--success .q-status__dot {
    background: var(--success);
    box-shadow: 0 0 0 3px var(--success-subtle);
}

.q-status--warning .q-status__dot {
    background: var(--warning);
    box-shadow: 0 0 0 3px var(--warning-subtle);
}

.q-status--danger .q-status__dot {
    background: var(--danger);
    box-shadow: 0 0 0 3px var(--danger-subtle);
}

.q-status--info .q-status__dot {
    background: var(--info);
    box-shadow: 0 0 0 3px var(--info-subtle);
}

.q-status--primary .q-status__dot {
    background: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-subtle);
}

/* Live pulse — for anything genuinely happening now (a visit in progress). */
.q-status--live .q-status__dot {
    background: var(--success);
    animation: q-pulse 1.9s var(--ease) infinite;
}

@keyframes q-pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(80,212,146,.45);
    }

    70% {
        box-shadow: 0 0 0 7px rgba(80,212,146,0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(80,212,146,0);
    }
}

/* Keycap */
.q-kbd {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 21px;
    height: 21px;
    padding: 0 5px;
    border: 1px solid var(--border-default);
    border-bottom-width: 2px;
    border-radius: 5px;
    background: var(--surface-2);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: 1;
}


/* ============================================================================
   9.  MODAL  /  MESSAGE BOX
   ============================================================================ */
.q-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-5);
    background: var(--modal-overlay);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--timing) var(--ease), visibility var(--timing) var(--ease);
}

    .q-modal-overlay.is-open {
        opacity: 1;
        visibility: visible;
    }

.q-modal {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 520px;
    max-height: calc(100vh - var(--sp-9));
    border: 1px solid var(--modal-border);
    border-radius: var(--modal-radius);
    background: var(--modal-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--modal-shadow);
    transform: translateY(14px) scale(.985);
    opacity: 0;
    transition: transform var(--timing) var(--ease-out), opacity var(--timing) var(--ease);
}

.q-modal-overlay.is-open .q-modal {
    transform: translateY(0) scale(1);
    opacity: 1;
}

.q-modal--sm {
    max-width: 400px;
}

.q-modal--lg {
    max-width: 720px;
}

.q-modal--xl {
    max-width: 960px;
}

.q-modal__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-6) var(--sp-6) var(--sp-4);
    flex: 0 0 auto;
}

.q-modal__title {
    font-size: var(--font-size-xl);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    color: var(--text-primary);
}

.q-modal__sub {
    margin-top: 5px;
    font-size: var(--font-size-sm);
    line-height: 1.5;
    color: var(--text-muted);
}

.q-modal__x {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    margin: -4px -4px 0 0;
    border: 0;
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: background-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease);
}

    .q-modal__x svg {
        width: 17px;
        height: 17px;
    }

    .q-modal__x:hover {
        background: var(--hover-bg-strong);
        color: var(--text-primary);
    }

.q-modal__body {
    flex: 1 1 auto;
    padding: 0 var(--sp-6) var(--sp-5);
    overflow-y: auto;
    font-size: var(--font-size-sm);
    line-height: var(--lh-base);
    color: var(--text-secondary);
}

.q-modal__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-6) var(--sp-6);
    flex: 0 0 auto;
}

.q-modal__foot--split {
    justify-content: space-between;
}

/* Message box — an icon-led confirm/alert. */
.q-msgbox {
    text-align: center;
    padding: var(--sp-7) var(--sp-6) var(--sp-6);
}

.q-msgbox__ico {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    margin: 0 auto var(--sp-4);
    border-radius: 50%;
    background: var(--primary-muted);
    color: var(--primary-bright);
}

    .q-msgbox__ico svg {
        width: 27px;
        height: 27px;
    }

.q-msgbox__ico--danger {
    background: var(--danger-muted);
    color: var(--danger);
}

.q-msgbox__ico--success {
    background: var(--success-muted);
    color: var(--success);
}

.q-msgbox__ico--warning {
    background: var(--warning-muted);
    color: var(--warning);
}

.q-msgbox__title {
    font-size: var(--font-size-xl);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    color: var(--text-primary);
}

.q-msgbox__text {
    max-width: 40ch;
    margin: var(--sp-3) auto 0;
    font-size: var(--font-size-sm);
    line-height: var(--lh-base);
    color: var(--text-muted);
}

@media (max-width: 560px) {
    .q-modal-overlay {
        padding: 0;
        align-items: flex-end;
    }

    .q-modal {
        max-width: none;
        max-height: 92vh;
        border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
        transform: translateY(100%);
    }

    .q-modal__foot {
        flex-direction: column-reverse;
    }

        .q-modal__foot .qbtn {
            width: 100%;
        }
}


/* ============================================================================
   10.  TOAST
   ============================================================================ */
.q-toaster {
    position: fixed;
    top: var(--sp-5);
    right: var(--sp-5);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    width: min(94vw, 384px);
    pointer-events: none;
}

.q-toaster--bottom {
    top: auto;
    bottom: var(--sp-5);
}

.q-toaster--center {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
}

.q-toast {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--glass-edge-strong);
    border-radius: var(--radius-md);
    background: var(--toast-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--highlight-top), var(--shadow-lg);
    pointer-events: auto;
    overflow: hidden;
    animation: q-toast-in var(--timing) var(--ease-out);
}

@keyframes q-toast-in {
    from {
        opacity: 0;
        transform: translateX(20px);
    }
}

.q-toast.is-leaving {
    animation: q-toast-out var(--timing-fast) var(--ease) forwards;
}

@keyframes q-toast-out {
    to {
        opacity: 0;
        transform: translateX(20px);
    }
}

/* A 3px accent rail on the leading edge carries the status colour. */
.q-toast::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 3px;
    background: var(--primary);
}

.q-toast--success::before {
    background: var(--success);
}

.q-toast--error::before {
    background: var(--danger);
}

.q-toast--warning::before {
    background: var(--warning);
}

.q-toast--info::before {
    background: var(--info);
}

.q-toast__ico {
    flex: 0 0 auto;
    width: 19px;
    height: 19px;
    margin-top: 1px;
    color: var(--primary);
}

.q-toast--success .q-toast__ico {
    color: var(--success);
}

.q-toast--error .q-toast__ico {
    color: var(--danger);
}

.q-toast--warning .q-toast__ico {
    color: var(--warning);
}

.q-toast--info .q-toast__ico {
    color: var(--info);
}

.q-toast__main {
    flex: 1 1 auto;
    min-width: 0;
}

.q-toast__title {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-toast__text {
    margin-top: 2px;
    font-size: var(--font-size-xs);
    line-height: 1.45;
    color: var(--text-muted);
}

.q-toast__x {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    margin: -2px -4px 0 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text-faint);
    cursor: pointer;
}

    .q-toast__x svg {
        width: 14px;
        height: 14px;
    }

    .q-toast__x:hover {
        background: var(--hover-bg-strong);
        color: var(--text-primary);
    }

@media (max-width: 560px) {
    .q-toaster {
        left: var(--sp-3);
        right: var(--sp-3);
        width: auto;
    }
}


/* ============================================================================
   11.  INLINE NOTE  /  BANNER
   ----------------------------------------------------------------------------
   Copy rule for these: say what happened and what to do next. No apologies,
   no "Oops". "Your card was declined. Try another card or contact your bank."
   ============================================================================ */
.q-note {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--note-bg);
    font-size: var(--font-size-sm);
    line-height: 1.55;
    color: var(--text-secondary);
}

.q-note__ico {
    flex: 0 0 auto;
    width: 19px;
    height: 19px;
    margin-top: 1px;
    color: var(--text-muted);
}

.q-note__main {
    flex: 1 1 auto;
    min-width: 0;
}

.q-note__title {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
    margin-bottom: 2px;
}

.q-note__actions {
    display: flex;
    gap: var(--sp-2);
    margin-top: var(--sp-3);
}

.q-note--primary {
    border-color: rgba(114,137,238,.24);
    background: var(--primary-subtle);
}

    .q-note--primary .q-note__ico {
        color: var(--primary);
    }

.q-note--success {
    border-color: rgba(80,212,146,.24);
    background: var(--success-subtle);
}

    .q-note--success .q-note__ico {
        color: var(--success);
    }

.q-note--warning {
    border-color: rgba(242,176,54,.24);
    background: var(--warning-subtle);
}

    .q-note--warning .q-note__ico {
        color: var(--warning);
    }

.q-note--danger {
    border-color: rgba(255,123,123,.24);
    background: var(--danger-subtle);
}

    .q-note--danger .q-note__ico {
        color: var(--danger);
    }

.q-note--info {
    border-color: rgba(55,198,255,.24);
    background: var(--info-subtle);
}

    .q-note--info .q-note__ico {
        color: var(--info);
    }


/* ============================================================================
   12.  MENU  /  POPOVER
   ============================================================================ */
.q-menu {
    position: absolute;
    z-index: var(--z-menu);
    min-width: 208px;
    padding: 6px;
    border: 1px solid var(--menu-border);
    border-radius: var(--menu-radius);
    background: var(--menu-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    box-shadow: var(--highlight-top), var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px) scale(.98);
    transform-origin: top right;
    transition: opacity var(--timing-fast) var(--ease), transform var(--timing-fast) var(--ease-out), visibility var(--timing-fast) var(--ease);
}

    .q-menu.is-open {
        opacity: 1;
        visibility: visible;
        transform: translateY(0) scale(1);
    }

.q-menu__item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 11px;
    border: 0;
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font);
    font-size: var(--font-size-sm);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease);
}

    .q-menu__item svg {
        width: 16px;
        height: 16px;
        flex: 0 0 auto;
        opacity: .8;
    }

    .q-menu__item:hover {
        background: var(--hover-bg-strong);
        color: var(--text-primary);
    }

    .q-menu__item.is-active {
        background: var(--primary-muted);
        color: var(--primary-bright);
    }

.q-menu__item--danger {
    color: var(--danger);
}

    .q-menu__item--danger:hover {
        background: var(--danger-muted);
        color: var(--danger);
    }

.q-menu__item[disabled] {
    opacity: .4;
    pointer-events: none;
}

.q-menu__shortcut {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: var(--font-size-xxs);
    color: var(--text-faint);
}

.q-menu__label {
    padding: 8px 11px 5px;
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-faint);
}

.q-menu__sep {
    height: 1px;
    margin: 5px 0;
    background: var(--border-subtle);
}


/* ============================================================================
   13.  TOOLTIP   (CSS-only: add .q-tip and data-tip to any element)
   ============================================================================ */
.q-tip {
    position: relative;
}

/* ── the JS tooltip ──────────────────────────────────────────────────────
   qlynic-ui.js adds .q-js to <html>, which retires the ::after version below
   in favour of one shared floating node it can position against the viewport.
   The CSS version stays as the no-JS fallback: correct everywhere except at
   the window edges, which is a better failure than nothing.               */

html.q-js .q-tip::after {
    content: none;
}

.q-tipbox {
    position: fixed;
    top: 0;
    left: -9999px;
    z-index: var(--z-toast);
    max-width: 280px;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 6px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--tooltip-bg);
    color: var(--text-primary);
    font-family: var(--font);
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-medium);
    line-height: 1.35;
    white-space: nowrap;
    box-shadow: var(--shadow-md);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(3px);
    transition: opacity var(--timing-fast) var(--ease), transform var(--timing-fast) var(--ease-out), visibility var(--timing-fast);
}

.q-tipbox__label {
    flex: 1 1 auto;
    min-width: 0;
}

/* A keyboard shortcut belongs in a key, not in the sentence. "Sidebar · ]"
   reads like a typo; "Sidebar" followed by a rendered ] key reads like an
   affordance. Set data-tip-key alongside data-tip. */
.q-tipbox__key {
    flex: 0 0 auto;
    min-width: 18px;
    padding: 2px 5px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--text-primary) 12%, transparent);
    border: 1px solid var(--border-strong);
    border-bottom-width: 2px;
    color: var(--text-secondary);
    font-family: var(--font);
    font-size: 10px;
    font-weight: var(--fw-bold);
    line-height: 1.1;
    text-align: center;
}

/* Icons inside a tooltip trigger must not receive pointer events. Without
   this, crossing from the button onto its own SVG fires mouseout/mouseover
   and the tooltip strobes. The script guards this too; belt and braces,
   because the visual glitch is very noticeable and very cheap to prevent. */
.q-tip svg,
.q-tip img,
.q-tip .q-ico,
[data-tip] > svg {
    pointer-events: none;
}

.q-tipbox--wrap {
    white-space: normal;
    max-width: 240px;
}

/* measuring pass — laid out, never painted */
.q-tipbox.is-measuring {
    visibility: hidden;
    opacity: 0;
    transition: none;
}

.q-tipbox.is-open {
    opacity: 1;
    visibility: visible;
    transform: none;
}

/* slide in from the side it is anchored to */
.q-tipbox[data-side="bottom"] {
    transform: translateY(-3px);
}

.q-tipbox[data-side="left"] {
    transform: translateX(3px);
}

.q-tipbox[data-side="right"] {
    transform: translateX(-3px);
}

.q-tipbox.is-open[data-side] {
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .q-tipbox {
        transition: none;
        transform: none;
    }
}

.q-tip::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(3px);
    z-index: var(--z-menu);
    padding: 6px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--tooltip-bg);
    color: var(--text-primary);
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-medium);
    line-height: 1.35;
    white-space: nowrap;
    box-shadow: var(--shadow-md);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--timing-fast) var(--ease), transform var(--timing-fast) var(--ease-out), visibility var(--timing-fast);
}

.q-tip:hover::after, .q-tip:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

.q-tip--bottom::after {
    bottom: auto;
    top: calc(100% + 8px);
    transform: translateX(-50%) translateY(-3px);
}

.q-tip--bottom:hover::after {
    transform: translateX(-50%) translateY(0);
}

.q-tip--left::after {
    bottom: auto;
    top: 50%;
    left: auto;
    right: calc(100% + 8px);
    transform: translateY(-50%) translateX(3px);
}

.q-tip--left:hover::after {
    transform: translateY(-50%) translateX(0);
}

.q-tip--right::after {
    bottom: auto;
    top: 50%;
    left: calc(100% + 8px);
    right: auto;
    transform: translateY(-50%) translateX(-3px);
}

.q-tip--right:hover::after {
    transform: translateY(-50%) translateX(0);
}

.q-tip--wrap::after {
    white-space: normal;
    width: max-content;
    max-width: 240px;
}


/* ============================================================================
   14.  TABLE
   ----------------------------------------------------------------------------
   On phones, wrap any table in .q-table-scroll. Below 640px a table can also
   take .q-table--stack, which turns each row into a labelled block using
   data-label attributes on the cells.
   ============================================================================ */
.q-table-scroll {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.q-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--font-size-sm);
}

    .q-table thead th {
        padding: 11px var(--sp-4);
        border-bottom: 1px solid var(--table-border);
        background: var(--table-head-bg);
        color: var(--table-head-text);
        font-size: var(--font-size-xxs);
        font-weight: var(--fw-bold);
        letter-spacing: var(--ls-caps);
        text-transform: uppercase;
        text-align: left;
        white-space: nowrap;
    }

        .q-table thead th:first-child {
            border-top-left-radius: var(--radius-sm);
            border-bottom-left-radius: var(--radius-sm);
        }

        .q-table thead th:last-child {
            border-top-right-radius: var(--radius-sm);
            border-bottom-right-radius: var(--radius-sm);
        }

    .q-table tbody td {
        padding: 13px var(--sp-4);
        border-bottom: 1px solid var(--table-border);
        color: var(--text-secondary);
        vertical-align: middle;
    }

    .q-table tbody tr {
        transition: background-color var(--timing-fast) var(--ease);
    }

        .q-table tbody tr:hover {
            background: var(--table-row-hover);
        }

        .q-table tbody tr:last-child td {
            border-bottom: 0;
        }

.q-table--striped tbody tr:nth-child(even) {
    background: var(--table-row-alt);
}

.q-table--compact tbody td {
    padding: 8px var(--sp-3);
}

.q-table--compact thead th {
    padding: 8px var(--sp-3);
}

.q-table__num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.q-table__act {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

.q-table__primary {
    color: var(--text-primary);
    font-weight: var(--fw-semibold);
}

.q-table th.is-sortable {
    cursor: pointer;
    user-select: none;
}

    .q-table th.is-sortable:hover {
        color: var(--text-secondary);
    }

@media (max-width: 640px) {
    .q-table--stack thead {
        display: none;
    }

    .q-table--stack tbody tr {
        display: block;
        margin-bottom: var(--sp-3);
        border: 1px solid var(--border-subtle);
        border-radius: var(--radius-md);
        background: var(--surface-1);
        padding: var(--sp-2) var(--sp-3);
    }

    .q-table--stack tbody td {
        display: flex;
        justify-content: space-between;
        gap: var(--sp-4);
        padding: 7px 0;
        border-bottom: 1px solid var(--border-subtle);
        text-align: right;
    }

        .q-table--stack tbody td:last-child {
            border-bottom: 0;
        }

        .q-table--stack tbody td::before {
            content: attr(data-label);
            flex: 0 0 auto;
            font-size: var(--font-size-xxs);
            font-weight: var(--fw-semibold);
            letter-spacing: var(--ls-caps);
            text-transform: uppercase;
            color: var(--text-faint);
            text-align: left;
        }
}


/* ============================================================================
   15.  LINKS
   ============================================================================ */
.q-link {
    color: var(--primary-bright);
    text-decoration: none;
    transition: color var(--timing-fast) var(--ease);
}

    .q-link:hover {
        color: var(--accent-bright);
        text-decoration: underline;
        text-underline-offset: 3px;
    }

.q-link--muted {
    color: var(--text-muted);
}

    .q-link--muted:hover {
        color: var(--text-primary);
    }

.q-link--quiet {
    color: inherit;
    text-decoration: none;
}

    .q-link--quiet:hover {
        color: var(--primary-bright);
        text-decoration: none;
    }


/* ============================================================================
   16.  SCROLLBARS   (opt-in: add .q-scroll to a scroll container)
   ============================================================================ */
.q-scroll {
    scrollbar-width: thin;
    scrollbar-color: var(--scroll-thumb) transparent;
}

    .q-scroll::-webkit-scrollbar {
        width: 10px;
        height: 10px;
    }

    .q-scroll::-webkit-scrollbar-track {
        background: transparent;
    }

    .q-scroll::-webkit-scrollbar-thumb {
        border: 3px solid transparent;
        border-radius: var(--radius-pill);
        background-clip: content-box;
        background-color: var(--scroll-thumb);
    }

        .q-scroll::-webkit-scrollbar-thumb:hover {
            background-color: var(--scroll-thumb-hover);
        }


/* ============================================================================
   17.  SKELETON
   ============================================================================ */
.q-skel {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-xs);
    background: var(--surface-2);
}

    .q-skel::after {
        content: "";
        position: absolute;
        inset: 0;
        transform: translateX(-100%);
        background: linear-gradient(90deg, transparent, rgba(255,255,255,.055), transparent);
        animation: q-shimmer 1.5s infinite;
    }

@keyframes q-shimmer {
    100% {
        transform: translateX(100%);
    }
}

.q-skel--text {
    height: 12px;
    margin-bottom: 8px;
    border-radius: 4px;
}

.q-skel--title {
    height: 19px;
    width: 42%;
    margin-bottom: 13px;
    border-radius: 5px;
}

.q-skel--circle {
    border-radius: 50%;
}

.q-skel--btn {
    height: 42px;
    width: 116px;
    border-radius: var(--radius-md);
}

.q-skel--card {
    height: 108px;
    border-radius: var(--radius-lg);
}

.q-skel--w40 {
    width: 40%;
}

.q-skel--w60 {
    width: 60%;
}

.q-skel--w80 {
    width: 80%;
}


/* ============================================================================
   18.  PROGRESS   (linear)
   ============================================================================ */
.q-progress {
    position: relative;
    height: 7px;
    width: 100%;
    border-radius: var(--radius-pill);
    background: var(--chart-track);
    overflow: hidden;
}

.q-progress__fill {
    height: 100%;
    border-radius: inherit;
    background: var(--primary);
    transition: width var(--timing-slow) var(--ease-out);
}

.q-progress--aurora .q-progress__fill {
    background: var(--aurora);
}

.q-progress--success .q-progress__fill {
    background: var(--success);
}

.q-progress--warning .q-progress__fill {
    background: var(--warning);
}

.q-progress--danger .q-progress__fill {
    background: var(--danger);
}

.q-progress--sm {
    height: 4px;
}

.q-progress--lg {
    height: 11px;
}

.q-progress--indet .q-progress__fill {
    width: 38%;
    animation: q-indet 1.25s var(--ease) infinite;
}

@keyframes q-indet {
    0% {
        transform: translateX(-100%);
    }

    100% {
        transform: translateX(300%);
    }
}

.q-progress-row {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.q-progress-row__val {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}


/* ============================================================================
   19.  SPINNER  +  PROGRESS RING
   ============================================================================ */
.q-spinner {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 2px solid var(--chart-track);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: q-spin .68s linear infinite;
}

.q-spinner--sm {
    width: 15px;
    height: 15px;
    border-width: 1.5px;
}

.q-spinner--lg {
    width: 32px;
    height: 32px;
    border-width: 3px;
}

.q-spinner--accent {
    border-top-color: var(--accent);
}

.q-spinner--light {
    border-color: rgba(255,255,255,.24);
    border-top-color: #fff;
}

.q-ring {
    position: relative;
    display: inline-grid;
    place-items: center;
}

    .q-ring svg {
        transform: rotate(-90deg);
    }

.q-ring__track {
    fill: none;
    stroke: var(--chart-track);
}

.q-ring__fill {
    fill: none;
    stroke: var(--primary);
    stroke-linecap: round;
    transition: stroke-dashoffset var(--timing-slow) var(--ease-out);
}

.q-ring__label {
    position: absolute;
    font-family: var(--font-mono);
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-ring--success .q-ring__fill {
    stroke: var(--success);
}

.q-ring--warning .q-ring__fill {
    stroke: var(--warning);
}

.q-ring--danger .q-ring__fill {
    stroke: var(--danger);
}


/* ============================================================================
   20.  AVATAR
   ============================================================================ */
.q-avatar {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--surface-4);
    color: var(--text-secondary);
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    letter-spacing: .01em;
    overflow: hidden;
    user-select: none;
}

    .q-avatar img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

.q-avatar--xs {
    width: 24px;
    height: 24px;
    font-size: 10px;
}

.q-avatar--sm {
    width: 32px;
    height: 32px;
    font-size: var(--font-size-xxs);
}

.q-avatar--lg {
    width: 52px;
    height: 52px;
    font-size: var(--font-size-lg);
}

.q-avatar--xl {
    width: 72px;
    height: 72px;
    font-size: var(--font-size-xxl);
}

.q-avatar--square {
    border-radius: var(--radius-md);
}

.q-avatar--primary {
    background: var(--primary-muted);
    color: var(--primary-bright);
}

.q-avatar--accent {
    background: var(--accent-muted);
    color: var(--accent);
}

.q-avatar--violet {
    background: var(--violet-muted);
    color: var(--violet);
}

.q-avatar--rose {
    background: var(--rose-muted);
    color: var(--rose);
}

.q-avatar--ring {
    box-shadow: 0 0 0 2px var(--bg-base), 0 0 0 4px var(--primary);
}

.q-avatar__badge {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 12px;
    height: 12px;
    border: 2px solid var(--bg-base);
    border-radius: 50%;
    background: var(--success);
}

.q-avatar-stack {
    display: inline-flex;
    align-items: center;
}

    .q-avatar-stack .q-avatar {
        margin-left: -10px;
        box-shadow: 0 0 0 2px var(--surface-3);
    }

        .q-avatar-stack .q-avatar:first-child {
            margin-left: 0;
        }


/* ============================================================================
   21.  TABS
   ============================================================================ */
.q-tabs {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    border-bottom: 1px solid var(--border-subtle);
    overflow-x: auto;
    scrollbar-width: none;
}

    .q-tabs::-webkit-scrollbar {
        display: none;
    }

.q-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 11px var(--sp-4);
    border: 0;
    background: transparent;
    color: var(--text-muted);
    font-family: var(--font);
    font-size: var(--font-size-sm);
    font-weight: var(--fw-medium);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--timing-fast) var(--ease);
}

    .q-tab svg {
        width: 16px;
        height: 16px;
    }

    .q-tab::after {
        content: "";
        position: absolute;
        left: var(--sp-3);
        right: var(--sp-3);
        bottom: -1px;
        height: 2px;
        border-radius: 2px 2px 0 0;
        background: var(--primary);
        transform: scaleX(0);
        transition: transform var(--timing) var(--ease-out);
    }

    .q-tab:hover {
        color: var(--text-secondary);
    }

    .q-tab.is-active {
        color: var(--text-primary);
        font-weight: var(--fw-semibold);
    }

        .q-tab.is-active::after {
            transform: scaleX(1);
        }

    .q-tab:focus-visible {
        outline: none;
        box-shadow: var(--ring);
        border-radius: var(--radius-xs);
    }

.q-tab__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 19px;
    height: 19px;
    padding: 0 5px;
    border-radius: var(--radius-pill);
    background: var(--surface-3);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: 11px;
}

.q-tab.is-active .q-tab__count {
    background: var(--primary-muted);
    color: var(--primary-bright);
}

/* Pill tabs — self-contained, no bottom rule. */
.q-tabs--pill {
    gap: 3px;
    padding: 4px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    background: var(--seg-bg);
}

    .q-tabs--pill .q-tab {
        padding: 8px var(--sp-4);
        border-radius: var(--radius-sm);
    }

        .q-tabs--pill .q-tab::after {
            display: none;
        }

        .q-tabs--pill .q-tab:hover {
            background: var(--hover-bg);
        }

        .q-tabs--pill .q-tab.is-active {
            background: var(--seg-thumb);
            box-shadow: var(--highlight-top), 0 1px 2px rgba(0,0,0,.30);
        }


/* ============================================================================
   22.  BREADCRUMB  +  PAGINATION
   ============================================================================ */
.q-crumbs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    font-size: var(--font-size-xs);
}

.q-crumbs__item {
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--timing-fast) var(--ease);
}

    .q-crumbs__item:hover {
        color: var(--text-primary);
    }

    .q-crumbs__item.is-current {
        color: var(--text-primary);
        font-weight: var(--fw-semibold);
    }

.q-crumbs__sep {
    color: var(--text-faint);
    user-select: none;
}

    .q-crumbs__sep svg {
        width: 13px;
        height: 13px;
    }

.q-pager {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    flex-wrap: wrap;
}

.q-pager__btn {
    display: grid;
    place-items: center;
    min-width: 36px;
    height: 36px;
    padding: 0 10px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    font-family: var(--font);
    font-size: var(--font-size-sm);
    font-weight: var(--fw-medium);
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease), border-color var(--timing-fast) var(--ease);
}

    .q-pager__btn svg {
        width: 16px;
        height: 16px;
    }

    .q-pager__btn:hover {
        background: var(--hover-bg-strong);
        color: var(--text-primary);
    }

    .q-pager__btn.is-active {
        background: var(--primary);
        color: #fff;
        font-weight: var(--fw-semibold);
    }

    .q-pager__btn[disabled] {
        opacity: .35;
        pointer-events: none;
    }

.q-pager__gap {
    display: grid;
    place-items: center;
    min-width: 26px;
    height: 36px;
    color: var(--text-faint);
}

.q-pager__info {
    margin-right: auto;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}


/* ============================================================================
   23.  EMPTY STATE
   ----------------------------------------------------------------------------
   An empty screen is an invitation, not an apology. Title says what's here,
   body says what to do, and there is always exactly one action.
   ============================================================================ */
.q-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--sp-9) var(--sp-5);
}

.q-empty__ico {
    display: grid;
    place-items: center;
    width: 62px;
    height: 62px;
    margin-bottom: var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: 50%;
    background: var(--surface-1);
    color: var(--text-faint);
}

    .q-empty__ico svg {
        width: 27px;
        height: 27px;
    }

.q-empty__title {
    font-size: var(--font-size-lg);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-empty__text {
    max-width: 44ch;
    margin-top: var(--sp-2);
    font-size: var(--font-size-sm);
    line-height: var(--lh-base);
    color: var(--text-muted);
}

.q-empty__actions {
    display: flex;
    gap: var(--sp-2);
    margin-top: var(--sp-5);
    flex-wrap: wrap;
    justify-content: center;
}

.q-empty--sm {
    padding: var(--sp-7) var(--sp-4);
}

    .q-empty--sm .q-empty__ico {
        width: 48px;
        height: 48px;
    }

        .q-empty--sm .q-empty__ico svg {
            width: 21px;
            height: 21px;
        }


/* ============================================================================
   24.  STEPPER / WIZARD
   ============================================================================ */
.q-steps {
    display: flex;
    align-items: flex-start;
    gap: 0;
}

.q-step {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 0 var(--sp-2);
}

    .q-step::before {
        content: "";
        position: absolute;
        top: 15px;
        left: -50%;
        width: 100%;
        height: 2px;
        background: var(--border-default);
    }

    .q-step:first-child::before {
        display: none;
    }

.q-step__dot {
    position: relative;
    z-index: 1;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border: 2px solid var(--border-default);
    border-radius: 50%;
    background: var(--bg-elevated);
    color: var(--text-faint);
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-semibold);
    transition: all var(--timing) var(--ease);
}

    .q-step__dot svg {
        width: 15px;
        height: 15px;
    }

.q-step__label {
    margin-top: var(--sp-2);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-medium);
    color: var(--text-muted);
}

.q-step__sub {
    margin-top: 2px;
    font-size: var(--font-size-xxs);
    color: var(--text-faint);
}

.q-step.is-active .q-step__dot {
    border-color: var(--primary);
    background: var(--primary);
    color: #fff;
    box-shadow: var(--ring-soft);
}

.q-step.is-active .q-step__label {
    color: var(--text-primary);
    font-weight: var(--fw-semibold);
}

.q-step.is-done .q-step__dot {
    border-color: var(--success);
    background: var(--success);
    color: var(--text-on-light);
}

.q-step.is-done::before, .q-step.is-active::before {
    background: var(--success);
}

.q-step.is-active::before {
    background: linear-gradient(90deg, var(--success), var(--primary));
}

@media (max-width: 640px) {
    .q-steps--stack {
        flex-direction: column;
        gap: var(--sp-4);
    }

        .q-steps--stack .q-step {
            flex-direction: row;
            align-items: center;
            gap: var(--sp-3);
            text-align: left;
            padding: 0;
        }

            .q-steps--stack .q-step::before {
                top: -14px;
                left: 15px;
                width: 2px;
                height: 14px;
            }

            .q-steps--stack .q-step .q-step__label {
                margin-top: 0;
            }
}


/* ============================================================================
   25.  ACCORDION
   ============================================================================ */
.q-acc {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    overflow: hidden;
}

.q-acc__item + .q-acc__item {
    border-top: 1px solid var(--border-subtle);
}

.q-acc__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    width: 100%;
    padding: var(--sp-4) var(--sp-5);
    border: 0;
    background: transparent;
    color: var(--text-primary);
    font-family: var(--font);
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--timing-fast) var(--ease);
}

    .q-acc__head:hover {
        background: var(--hover-bg);
    }

.q-acc__chev {
    flex: 0 0 auto;
    width: 17px;
    height: 17px;
    color: var(--text-muted);
    transition: transform var(--timing) var(--ease);
}

.q-acc__item.is-open .q-acc__chev {
    transform: rotate(180deg);
}

.q-acc__body {
    display: none;
    padding: 0 var(--sp-5) var(--sp-5);
    font-size: var(--font-size-sm);
    line-height: var(--lh-base);
    color: var(--text-muted);
}

.q-acc__item.is-open .q-acc__body {
    display: block;
    animation: q-fade-down var(--timing) var(--ease-out);
}

@keyframes q-fade-down {
    from {
        opacity: 0;
        transform: translateY(-5px);
    }
}


/* ============================================================================
   26.  STAT CARD  +  KEY-VALUE ROWS
   ============================================================================ */
.q-stat {
    position: relative;
    padding: var(--sp-5);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    overflow: hidden;
}

.q-stat__label {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-faint);
}

    .q-stat__label svg {
        width: 14px;
        height: 14px;
    }

.q-stat__value {
    margin-top: 10px;
    font-size: var(--font-size-display);
    font-weight: var(--fw-black);
    letter-spacing: -.03em;
    line-height: 1;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.q-stat__unit {
    margin-left: 4px;
    font-size: var(--font-size-lg);
    font-weight: var(--fw-semibold);
    color: var(--text-muted);
}

.q-stat__meta {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: var(--sp-3);
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-stat__delta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-weight: var(--fw-semibold);
}

    .q-stat__delta svg {
        width: 13px;
        height: 13px;
    }

.q-stat__delta--up {
    color: var(--success);
}

.q-stat__delta--down {
    color: var(--danger);
}

.q-stat--focal {
    background: var(--surface-tint);
    border-color: rgba(114,137,238,.20);
}

    .q-stat--focal::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 1px;
        background: var(--aurora-band);
        opacity: .8;
    }

.q-kv {
    display: flex;
    flex-direction: column;
}

.q-kv__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: 11px 0;
    border-bottom: 1px solid var(--border-subtle);
}

    .q-kv__row:last-child {
        border-bottom: 0;
    }

.q-kv__k {
    flex: 0 0 auto;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-kv__v {
    text-align: right;
    font-size: var(--font-size-sm);
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.q-kv__v--strong {
    font-weight: var(--fw-bold);
    font-size: var(--font-size-lg);
}

.q-kv--total {
    border-top: 1px solid var(--border-default);
    margin-top: var(--sp-2);
    padding-top: var(--sp-2);
}


/* ============================================================================
   27.  DROPZONE
   ============================================================================ */
.q-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--sp-7) var(--sp-5);
    border: 1.5px dashed var(--border-strong);
    border-radius: var(--radius-lg);
    background: var(--surface-0);
    cursor: pointer;
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease);
}

    .q-drop:hover, .q-drop.is-over {
        border-color: var(--primary);
        background: var(--primary-subtle);
    }

.q-drop__ico {
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    margin-bottom: var(--sp-3);
    border-radius: 50%;
    background: var(--surface-3);
    color: var(--text-muted);
}

    .q-drop__ico svg {
        width: 21px;
        height: 21px;
    }

.q-drop.is-over .q-drop__ico {
    background: var(--primary-muted);
    color: var(--primary-bright);
}

.q-drop__title {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-drop__hint {
    margin-top: 4px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}


/* ============================================================================
   28.  DRAWER   (right by default; --left variant)
   ============================================================================ */
.q-drawer-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer);
    background: var(--drawer-overlay);
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(5px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--timing) var(--ease), visibility var(--timing) var(--ease);
}

    .q-drawer-overlay.is-open {
        opacity: 1;
        visibility: visible;
    }

.q-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: calc(var(--z-drawer) + 1);
    display: flex;
    flex-direction: column;
    width: var(--drawer-width);
    border-left: 1px solid var(--border-default);
    background: var(--drawer-bg);
    box-shadow: var(--shadow-xl);
    transform: translateX(100%);
    transition: transform var(--timing-slow) var(--ease-out);
}

    .q-drawer.is-open {
        transform: translateX(0);
    }

.q-drawer--left {
    right: auto;
    left: 0;
    border-left: 0;
    border-right: 1px solid var(--border-default);
    transform: translateX(-100%);
}

.q-drawer__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-5) var(--sp-5) var(--sp-4);
    border-bottom: 1px solid var(--border-subtle);
    flex: 0 0 auto;
}

.q-drawer__title {
    font-size: var(--font-size-lg);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-snug);
    color: var(--text-primary);
}

.q-drawer__sub {
    margin-top: 3px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-drawer__body {
    flex: 1 1 auto;
    padding: var(--sp-5);
    overflow-y: auto;
}

.q-drawer__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-5);
    border-top: 1px solid var(--border-subtle);
    background: var(--drawer-bg);
    flex: 0 0 auto;
}

@media (max-width: 560px) {
    .q-drawer {
        width: 100%;
        border-left: 0;
        border-radius: 0;
    }
}


/* ============================================================================
   29.  PAGE HEADER
   ============================================================================ */
.q-pagehead {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-5);
    flex-wrap: wrap;
    padding-bottom: var(--sp-5);
    margin-bottom: var(--sp-6);
    border-bottom: 1px solid var(--border-subtle);
}

.q-pagehead__main {
    min-width: 0;
}

.q-pagehead__title {
    margin-top: 7px;
    font-size: var(--font-size-xxl);
    font-weight: var(--fw-black);
    letter-spacing: var(--ls-tight);
    line-height: 1.1;
    color: var(--text-primary);
}

.q-pagehead__sub {
    margin-top: 7px;
    max-width: 62ch;
    font-size: var(--font-size-sm);
    line-height: 1.55;
    color: var(--text-muted);
}

.q-pagehead__actions {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex: 0 0 auto;
    flex-wrap: wrap;
}

@media (max-width: 640px) {
    .q-pagehead {
        align-items: stretch;
    }

    .q-pagehead__actions {
        width: 100%;
    }

        .q-pagehead__actions .qbtn {
            flex: 1 1 auto;
        }
}


/* ############################################################################
   PART TWO  ·  PATIENT-DOMAIN COMPONENTS
   ----------------------------------------------------------------------------
   Everything above this line is generic UI that any dashboard could use.
   Everything below is specific to what a patient portal actually shows:
   appointments, results, messages, documents, payments, care teams.

   These exist because they were being rebuilt by hand on every page, slightly
   differently each time. An appointment card is the single most repeated object
   in this product — it deserves to be a component, not a convention.
   ############################################################################ */


/* ============================================================================
   30.  APPOINTMENT CARD
   ----------------------------------------------------------------------------
   The date block on the left is deliberately the loudest thing in the card.
   When someone opens this portal, "when" is almost always the question they
   came to answer.

   States: default · .is-next (the soonest upcoming) · .is-past · .is-cancelled
   ============================================================================ */
.q-appt {
    position: relative;
    display: flex;
    align-items: stretch;
    gap: var(--sp-4);
    padding: var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    transition: border-color var(--timing) var(--ease), background-color var(--timing) var(--ease), transform var(--timing) var(--ease-out);
}

    .q-appt:hover {
        transform: translateY(-2px);
        border-color: var(--border-default);
        background: var(--surface-2);
    }

.q-appt__date {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 62px;
    padding: var(--sp-3) 0;
    border-radius: var(--radius-md);
    background: var(--surface-3);
    text-align: center;
}

.q-appt__month {
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-muted);
}

.q-appt__day {
    margin-top: 1px;
    font-size: 1.625rem;
    font-weight: var(--fw-black);
    letter-spacing: -.03em;
    line-height: 1.05;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.q-appt__weekday {
    margin-top: 1px;
    font-size: 11px;
    color: var(--text-faint);
}

.q-appt__main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
}

.q-appt__title {
    font-size: var(--font-size-base);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--ls-snug);
    color: var(--text-primary);
}

.q-appt__meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-1) var(--sp-3);
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-appt__metaitem {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

    .q-appt__metaitem svg {
        width: 14px;
        height: 14px;
        flex: 0 0 auto;
        opacity: .75;
    }

.q-appt__tags {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 2px;
}

.q-appt__actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

/* The soonest appointment gets the aurora edge and a tinted ground. This is
   the one card on the page allowed to use the signature. */
.q-appt.is-next {
    background: var(--surface-tint);
    border-color: rgba(114,137,238,.24);
    box-shadow: var(--highlight-top), var(--shadow-md);
}

    .q-appt.is-next::before {
        content: "";
        position: absolute;
        top: 0;
        left: 20px;
        right: 20px;
        height: 1px;
        background: var(--aurora-band);
        opacity: .8;
        border-radius: 1px;
    }

    .q-appt.is-next .q-appt__date {
        background: var(--primary);
    }

    .q-appt.is-next .q-appt__month {
        color: rgba(255,255,255,.78);
    }

    .q-appt.is-next .q-appt__day {
        color: #fff;
    }

    .q-appt.is-next .q-appt__weekday {
        color: rgba(255,255,255,.62);
    }

.q-appt.is-past {
    opacity: .68;
}

    .q-appt.is-past:hover {
        opacity: 1;
    }

.q-appt.is-cancelled .q-appt__title {
    text-decoration: line-through;
    text-decoration-color: var(--text-faint);
    color: var(--text-muted);
}

.q-appt.is-cancelled .q-appt__date {
    background: var(--surface-2);
}

    .q-appt.is-cancelled .q-appt__date .q-appt__day {
        color: var(--text-muted);
    }

@media (max-width: 640px) {
    .q-appt {
        flex-wrap: wrap;
    }

    .q-appt__actions {
        width: 100%;
        padding-top: var(--sp-3);
        border-top: 1px solid var(--border-subtle);
    }

        .q-appt__actions .qbtn {
            flex: 1 1 auto;
        }
}


/* ============================================================================
   31.  RESULT READOUT   (labs, vitals, measurements)
   ----------------------------------------------------------------------------
   A number on its own is not information. A number with its unit, its
   reference range, and a position marker is. The bar shows where this patient
   sits inside the normal range — the single most reassuring thing you can put
   on a results page, and the thing patients otherwise Google at 2am.

   Flags: .is-normal · .is-low · .is-high · .is-critical
   ============================================================================ */
.q-result {
    padding: var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-1);
}

.q-result__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-3);
}

.q-result__name {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-result__code {
    margin-top: 1px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-faint);
}

.q-result__value {
    display: flex;
    align-items: baseline;
    gap: 5px;
    margin-top: var(--sp-3);
}

.q-result__num {
    font-size: var(--font-size-xxl);
    font-weight: var(--fw-bold);
    letter-spacing: -.025em;
    line-height: 1;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.q-result__unit {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}

/* Range bar: a track with a shaded "normal" band and a marker. */
.q-result__range {
    margin-top: var(--sp-4);
}

.q-result__track {
    position: relative;
    height: 6px;
    border-radius: var(--radius-pill);
    background: var(--chart-track);
    overflow: visible;
}

.q-result__band {
    position: absolute;
    top: 0;
    bottom: 0;
    border-radius: var(--radius-pill);
    background: var(--success-muted);
}

.q-result__marker {
    position: absolute;
    top: 50%;
    width: 3px;
    height: 16px;
    margin-top: -8px;
    margin-left: -1.5px;
    border-radius: 2px;
    background: var(--text-primary);
    box-shadow: 0 0 0 2px var(--surface-1);
}

.q-result__scale {
    display: flex;
    justify-content: space-between;
    margin-top: 7px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-faint);
}

.q-result__note {
    margin-top: var(--sp-3);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--border-subtle);
    font-size: var(--font-size-xs);
    line-height: 1.5;
    color: var(--text-muted);
}

.q-result.is-low {
    border-color: rgba(55,198,255,.24);
}

    .q-result.is-low .q-result__num {
        color: var(--info);
    }

    .q-result.is-low .q-result__marker {
        background: var(--info);
    }

.q-result.is-high {
    border-color: rgba(242,176,54,.24);
}

    .q-result.is-high .q-result__num {
        color: var(--warning);
    }

    .q-result.is-high .q-result__marker {
        background: var(--warning);
    }

.q-result.is-critical {
    border-color: rgba(255,123,123,.30);
    background: var(--danger-subtle);
}

    .q-result.is-critical .q-result__num {
        color: var(--danger);
    }

    .q-result.is-critical .q-result__marker {
        background: var(--danger);
    }

.q-result.is-normal .q-result__num {
    color: var(--success);
}

.q-result.is-normal .q-result__marker {
    background: var(--success);
}


/* ============================================================================
   32.  MESSAGE THREAD
   ----------------------------------------------------------------------------
   Inbound (from the clinic) sits left on a neutral surface. Outbound (from the
   patient) sits right on indigo. Deliberately NOT a chat-app clone: the
   corners are calmer and the timestamps are always visible, because these
   messages are part of a medical record, not a conversation you scroll past.
   ============================================================================ */
.q-thread {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.q-msg {
    display: flex;
    gap: var(--sp-3);
    max-width: 82%;
}

.q-msg--out {
    flex-direction: row-reverse;
    margin-left: auto;
}

.q-msg__body {
    min-width: 0;
}

.q-msg__bubble {
    padding: 11px var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    border-top-left-radius: var(--radius-xs);
    background: var(--surface-2);
    font-size: var(--font-size-sm);
    line-height: 1.55;
    color: var(--text-secondary);
}

.q-msg--out .q-msg__bubble {
    border-color: transparent;
    border-radius: var(--radius-lg);
    border-top-right-radius: var(--radius-xs);
    background: var(--btn-primary);
    color: #fff;
}

.q-msg__meta {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-faint);
}

.q-msg--out .q-msg__meta {
    justify-content: flex-end;
}

.q-msg__sender {
    font-weight: var(--fw-semibold);
    color: var(--text-muted);
}

/* Attachment inside a bubble. */
.q-msg__file {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: var(--sp-3);
    padding: 9px 11px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: rgba(0,0,0,.22);
    font-size: var(--font-size-xs);
    text-decoration: none;
    color: inherit;
}

    .q-msg__file svg {
        width: 17px;
        height: 17px;
        flex: 0 0 auto;
        opacity: .8;
    }

/* Day separator inside a thread. */
.q-thread__day {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin: var(--sp-2) 0;
    font-size: 11px;
    font-weight: var(--fw-semibold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-faint);
}

    .q-thread__day::before, .q-thread__day::after {
        content: "";
        flex: 1 1 auto;
        height: 1px;
        background: var(--border-subtle);
    }

/* Typing indicator. */
.q-typing {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 13px var(--sp-4);
    border-radius: var(--radius-lg);
    background: var(--surface-2);
}

    .q-typing span {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: var(--text-faint);
        animation: q-typing 1.3s var(--ease) infinite;
    }

        .q-typing span:nth-child(2) {
            animation-delay: .16s;
        }

        .q-typing span:nth-child(3) {
            animation-delay: .32s;
        }

@keyframes q-typing {
    0%, 60%, 100% {
        opacity: .3;
        transform: translateY(0);
    }

    30% {
        opacity: 1;
        transform: translateY(-3px);
    }
}

/* Composer. */
.q-composer {
    display: flex;
    align-items: flex-end;
    gap: var(--sp-2);
    padding: var(--sp-3);
    border: 1px solid var(--field-border);
    border-radius: var(--radius-lg);
    background: var(--field-bg);
    transition: border-color var(--timing-fast) var(--ease), box-shadow var(--timing-fast) var(--ease);
}

    .q-composer:focus-within {
        border-color: var(--field-border-focus);
        box-shadow: var(--ring-soft);
    }

.q-composer__field {
    flex: 1 1 auto;
    min-height: 38px;
    max-height: 160px;
    padding: 9px 4px;
    border: 0;
    background: transparent;
    color: var(--field-text);
    font-family: var(--font);
    font-size: var(--font-size-sm);
    line-height: 1.5;
    resize: none;
}

    .q-composer__field:focus {
        outline: none;
    }

    .q-composer__field::placeholder {
        color: var(--field-placeholder);
    }

@media (max-width: 640px) {
    .q-msg {
        max-width: 92%;
    }
}


/* ============================================================================
   33.  TIMELINE   (care history, visit journey, audit trail)
   ============================================================================ */
.q-timeline {
    position: relative;
    padding-left: var(--sp-6);
}

    .q-timeline::before {
        content: "";
        position: absolute;
        top: 6px;
        bottom: 6px;
        left: 9px;
        width: 2px;
        border-radius: 2px;
        background: var(--border-default);
    }

.q-tl {
    position: relative;
    padding-bottom: var(--sp-6);
}

    .q-tl:last-child {
        padding-bottom: 0;
    }

.q-tl__dot {
    position: absolute;
    top: 3px;
    left: calc(var(--sp-6) * -1 + 3px);
    display: grid;
    place-items: center;
    width: 15px;
    height: 15px;
    border: 2px solid var(--bg-base);
    border-radius: 50%;
    background: var(--surface-4);
}

    .q-tl__dot svg {
        width: 9px;
        height: 9px;
        color: #fff;
    }

.q-tl--primary .q-tl__dot {
    background: var(--primary);
}

.q-tl--success .q-tl__dot {
    background: var(--success);
}

.q-tl--warning .q-tl__dot {
    background: var(--warning);
}

.q-tl--danger .q-tl__dot {
    background: var(--danger);
}

.q-tl__time {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-faint);
}

.q-tl__title {
    margin-top: 2px;
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-tl__text {
    margin-top: 3px;
    font-size: var(--font-size-xs);
    line-height: 1.55;
    color: var(--text-muted);
}

.q-tl__card {
    margin-top: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-1);
}


/* ============================================================================
   34.  DOCUMENT ROW   (results, receipts, letters, forms)
   ============================================================================ */
.q-doc {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease);
}

    .q-doc:hover {
        border-color: var(--border-default);
        background: var(--surface-2);
    }

.q-doc__ico {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-sm);
    background: var(--surface-3);
    color: var(--text-muted);
}

    .q-doc__ico svg {
        width: 19px;
        height: 19px;
    }

.q-doc__ico--pdf {
    background: var(--danger-muted);
    color: var(--danger);
}

.q-doc__ico--img {
    background: var(--violet-muted);
    color: var(--violet);
}

.q-doc__ico--lab {
    background: var(--accent-muted);
    color: var(--accent);
}

.q-doc__main {
    flex: 1 1 auto;
    min-width: 0;
}

.q-doc__name {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-medium);
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.q-doc__meta {
    margin-top: 2px;
    font-size: 11px;
    color: var(--text-faint);
}

.q-doc__actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
}

.q-doc.is-new .q-doc__name::after {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    margin-left: 7px;
    border-radius: 50%;
    background: var(--primary);
    vertical-align: middle;
}


/* ============================================================================
   35.  CARE TEAM CARD
   ============================================================================ */
.q-person {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease);
}

    .q-person:hover {
        border-color: var(--border-default);
        background: var(--surface-2);
    }

.q-person__main {
    flex: 1 1 auto;
    min-width: 0;
}

.q-person__name {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-person__role {
    margin-top: 1px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.q-person__meta {
    margin-top: 5px;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    font-size: 11px;
    color: var(--text-faint);
}

.q-person__actions {
    flex: 0 0 auto;
    display: flex;
    gap: 4px;
}


/* ============================================================================
   36.  DATE STRIP   (a week of pickable days — booking, availability)
   ============================================================================ */
.q-datestrip {
    display: flex;
    gap: var(--sp-2);
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: none;
}

    .q-datestrip::-webkit-scrollbar {
        display: none;
    }

.q-date {
    position: relative;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    width: 60px;
    height: 72px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    color: var(--text-secondary);
    cursor: pointer;
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease), transform var(--timing-fast) var(--ease-out);
}

    .q-date:hover {
        transform: translateY(-2px);
        border-color: var(--border-strong);
        background: var(--surface-2);
    }

.q-date__dow {
    font-size: 11px;
    font-weight: var(--fw-semibold);
    letter-spacing: var(--ls-wide);
    text-transform: uppercase;
    color: var(--text-faint);
}

.q-date__num {
    font-size: var(--font-size-lg);
    font-weight: var(--fw-bold);
    line-height: 1.1;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.q-date__slots {
    font-size: 10px;
    color: var(--text-faint);
}

.q-date.is-selected {
    border-color: var(--primary);
    background: var(--primary);
}

    .q-date.is-selected .q-date__dow, .q-date.is-selected .q-date__slots {
        color: rgba(255,255,255,.72);
    }

    .q-date.is-selected .q-date__num {
        color: #fff;
    }

.q-date.is-today::after {
    content: "";
    position: absolute;
    bottom: 6px;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--accent);
}

.q-date[disabled], .q-date.is-full {
    opacity: .38;
    pointer-events: none;
}

/* Time slots grid. */
.q-slots {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
    gap: var(--sp-2);
}

.q-slot {
    height: 40px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--surface-1);
    color: var(--text-secondary);
    font-family: var(--font);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-medium);
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: border-color var(--timing-fast) var(--ease), background-color var(--timing-fast) var(--ease), color var(--timing-fast) var(--ease);
}

    .q-slot:hover {
        border-color: var(--border-interactive);
        background: var(--surface-2);
        color: var(--text-primary);
    }

    .q-slot.is-selected {
        border-color: var(--primary);
        background: var(--primary);
        color: #fff;
    }

    .q-slot[disabled] {
        opacity: .32;
        pointer-events: none;
        text-decoration: line-through;
    }


/* ============================================================================
   37.  PAYMENT SUMMARY
   ============================================================================ */
.q-money {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: -.02em;
}

.q-money--lg {
    font-size: var(--font-size-xxl);
    font-weight: var(--fw-bold);
    color: var(--text-primary);
}

.q-money--due {
    color: var(--warning);
}

.q-money--paid {
    color: var(--success);
}

.q-money--overdue {
    color: var(--danger);
}

.q-summary {
    padding: var(--sp-5);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-0);
    box-shadow: inset 0 1px 3px rgba(0,0,0,.26);
}

.q-summary__total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    margin-top: var(--sp-3);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--border-default);
}

.q-summary__totallabel {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

/* Payment method row. */
.q-paymethod {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--surface-1);
}

.q-paymethod__brand {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 42px;
    height: 28px;
    border: 1px solid var(--border-subtle);
    border-radius: 5px;
    background: var(--surface-3);
    font-size: 10px;
    font-weight: var(--fw-bold);
    letter-spacing: .04em;
    color: var(--text-secondary);
}

.q-paymethod__num {
    font-family: var(--font-mono);
    font-size: var(--font-size-sm);
    color: var(--text-primary);
    letter-spacing: .04em;
}

.q-paymethod__exp {
    font-size: 11px;
    color: var(--text-faint);
}


/* ============================================================================
   38.  PAGE BANNER   (page-level alert — action required, portal notices)
   ============================================================================ */
.q-banner {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
}

.q-banner__ico {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    border-radius: var(--radius-md);
    background: var(--surface-3);
    color: var(--text-muted);
}

    .q-banner__ico svg {
        width: 20px;
        height: 20px;
    }

.q-banner__main {
    flex: 1 1 auto;
    min-width: 0;
}

.q-banner__title {
    font-size: var(--font-size-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.q-banner__text {
    margin-top: 2px;
    font-size: var(--font-size-xs);
    line-height: 1.5;
    color: var(--text-muted);
}

.q-banner__actions {
    flex: 0 0 auto;
    display: flex;
    gap: var(--sp-2);
}

.q-banner--action {
    border-color: rgba(242,176,54,.26);
    background: var(--warning-subtle);
}

    .q-banner--action .q-banner__ico {
        background: var(--warning-muted);
        color: var(--warning);
    }

.q-banner--urgent {
    border-color: rgba(255,123,123,.28);
    background: var(--danger-subtle);
}

    .q-banner--urgent .q-banner__ico {
        background: var(--danger-muted);
        color: var(--danger);
    }

.q-banner--good {
    border-color: rgba(80,212,146,.26);
    background: var(--success-subtle);
}

    .q-banner--good .q-banner__ico {
        background: var(--success-muted);
        color: var(--success);
    }

@media (max-width: 640px) {
    .q-banner {
        flex-wrap: wrap;
    }

    .q-banner__actions {
        width: 100%;
    }

        .q-banner__actions .qbtn {
            flex: 1 1 auto;
        }
}


/* ============================================================================
   39.  CONSENT BLOCK   (intake forms, sharing, telehealth agreements)
   ============================================================================ */
.q-consent {
    padding: var(--sp-5);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
}

.q-consent__scroll {
    max-height: 200px;
    overflow-y: auto;
    padding: var(--sp-4);
    margin-bottom: var(--sp-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-0);
    font-size: var(--font-size-xs);
    line-height: 1.65;
    color: var(--text-muted);
}

.q-consent__sign {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--border-subtle);
}

.q-consent__signature {
    flex: 1 1 auto;
    font-family: "Georgia", "Times New Roman", serif;
    font-style: italic;
    font-size: var(--font-size-lg);
    color: var(--text-primary);
}


/* ============================================================================
   40.  UTILITIES   (minimal + namespaced — layout only, no styling opinions)
   ============================================================================ */
.q-flex {
    display: flex;
}

.q-inline-flex {
    display: inline-flex;
}

.q-grid {
    display: grid;
}

.q-block {
    display: block;
}

.q-hidden {
    display: none !important;
}

.q-col {
    flex-direction: column;
}

.q-wrap {
    flex-wrap: wrap;
}

.q-center {
    align-items: center;
}

.q-start {
    align-items: flex-start;
}

.q-end {
    align-items: flex-end;
}

.q-baseline {
    align-items: baseline;
}

.q-between {
    justify-content: space-between;
}

.q-jcenter {
    justify-content: center;
}

.q-jend {
    justify-content: flex-end;
}

.q-grow {
    flex: 1 1 auto;
    min-width: 0;
}

.q-noshrink {
    flex: 0 0 auto;
}

.q-g1 {
    gap: var(--sp-1);
}

.q-g2 {
    gap: var(--sp-2);
}

.q-g3 {
    gap: var(--sp-3);
}

.q-g4 {
    gap: var(--sp-4);
}

.q-g5 {
    gap: var(--sp-5);
}

.q-g6 {
    gap: var(--sp-6);
}

.q-mt1 {
    margin-top: var(--sp-1);
}

.q-mt2 {
    margin-top: var(--sp-2);
}

.q-mt3 {
    margin-top: var(--sp-3);
}

.q-mt4 {
    margin-top: var(--sp-4);
}

.q-mt5 {
    margin-top: var(--sp-5);
}

.q-mt6 {
    margin-top: var(--sp-6);
}

.q-mt7 {
    margin-top: var(--sp-7);
}

.q-mt8 {
    margin-top: var(--sp-8);
}

.q-mt9 {
    margin-top: var(--sp-9);
}

.q-mt10 {
    margin-top: var(--sp-10);
}

.q-mb1 {
    margin-bottom: var(--sp-1);
}

.q-mb2 {
    margin-bottom: var(--sp-2);
}

.q-mb3 {
    margin-bottom: var(--sp-3);
}

.q-mb4 {
    margin-bottom: var(--sp-4);
}

.q-mb5 {
    margin-bottom: var(--sp-5);
}

.q-mb6 {
    margin-bottom: var(--sp-6);
}

.q-mb7 {
    margin-bottom: var(--sp-7);
}

.q-mb8 {
    margin-bottom: var(--sp-8);
}

.q-mb9 {
    margin-bottom: var(--sp-9);
}

.q-mb10 {
    margin-bottom: var(--sp-10);
}

.q-full {
    width: 100%;
}

.q-tright {
    text-align: right;
}

.q-tcenter {
    text-align: center;
}

.q-rel {
    position: relative;
}

.q-cols-2 {
    grid-template-columns: repeat(2, minmax(0,1fr));
}

.q-cols-3 {
    grid-template-columns: repeat(3, minmax(0,1fr));
}

.q-cols-4 {
    grid-template-columns: repeat(4, minmax(0,1fr));
}

.q-cols-auto {
    grid-template-columns: repeat(auto-fill, minmax(min(240px,100%), 1fr));
}

@media (max-width: 900px) {
    .q-cols-4 {
        grid-template-columns: repeat(2, minmax(0,1fr));
    }

    .q-cols-3 {
        grid-template-columns: repeat(2, minmax(0,1fr));
    }
}

@media (max-width: 600px) {
    .q-cols-2, .q-cols-3, .q-cols-4 {
        grid-template-columns: 1fr;
    }

    .q-hide-sm {
        display: none !important;
    }
}

@media (min-width: 601px) {
    .q-only-sm {
        display: none !important;
    }
}

/* Screen-reader-only, but still focusable when it needs to be. */
.q-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border: 0;
}


/* ============================================================================
   41.  GLASS FALLBACK
   ----------------------------------------------------------------------------
   Engines without backdrop-filter get opaque surfaces instead of a muddy
   translucent wash. Better to lose the effect than to lose the legibility.
   ============================================================================ */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .q-panel, .q-bar {
        background: var(--surface-3);
    }

    .q-card {
        background: var(--surface-2);
    }

    .q-menu, .q-toast {
        background: var(--surface-4);
    }

    .q-modal {
        background: var(--surface-5);
    }

    .q-modal-overlay, .q-drawer-overlay {
        background: rgba(2,3,8,.90);
    }
}

/* Windows High Contrast / forced-colors: let the OS win. */
@media (forced-colors: active) {
    .qbtn, .q-input, .q-select, .q-panel, .q-card {
        border: 1px solid ButtonBorder;
    }

        .qbtn:focus-visible, .q-input:focus {
            outline: 2px solid Highlight;
        }
}

/* ============================================================================
   42.  CHART  ·  FRAME
   ----------------------------------------------------------------------------
   A chart is a JS-rendered <canvas>/<svg> (Chart.js, D3, hand-rolled). The kit
   styles the FRAME around it — title, sub, plot area, footer — so every chart
   on every founder page shares one silhouette. Drop the frame inside a .q-panel
   or .q-card; the plot library owns .q-chart__body.
   ============================================================================ */
.q-chart {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.q-chart__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
}

.q-chart__title {
    font-size: var(--font-size-lg);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-snug);
    color: var(--text-primary);
}

.q-chart__sub {
    margin-top: 2px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

/* The plot surface. Give it height here so the library has a box to fill;
   the canvas/svg stretches to it. */
.q-chart__body {
    position: relative;
    width: 100%;
    min-height: 224px;
}

    .q-chart__body > canvas,
    .q-chart__body > svg {
        display: block;
        width: 100%;
        height: 100%;
    }

.q-chart__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-wrap: wrap;
}

.q-chart--sm .q-chart__body {
    min-height: 140px;
}

.q-chart--lg .q-chart__body {
    min-height: 340px;
}

/* --- Hand-rolled SVG helpers (skip if the library draws its own axes) ----- */
.q-chart__grid line,
.q-chart__grid path {
    stroke: var(--chart-grid);
    stroke-width: 1;
    shape-rendering: crispEdges;
}

.q-chart__axis line,
.q-chart__axis path {
    stroke: var(--chart-axis);
    stroke-width: 1;
}

.q-chart__tick {
    fill: var(--text-faint);
    font-family: var(--font-mono);
    font-size: var(--font-size-xxs);
}

/* Area fill under a line: reference the tokens from a gradient <def>, e.g.
   <linearGradient id="qArea" x1="0" y1="0" x2="0" y2="1">
     <stop offset="0"  stop-color="var(--chart-area-from)"/>
     <stop offset="1"  stop-color="var(--chart-area-to)"/>
   </linearGradient>  then  fill="url(#qArea)". */
.q-chart__line {
    fill: none;
    stroke: var(--chart-1);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}


/* ============================================================================
   43.  CHART  ·  LEGEND
   ----------------------------------------------------------------------------
   Series colour comes from a per-item custom prop so the legend, the plot, and
   the tooltip all read the same source:  <span class="q-legend__item"
   style="--c:var(--chart-2)"> …  Use the --btn variant for a clickable legend
   that toggles a series (add .is-off from your JS).
   ============================================================================ */
.q-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-4);
}

.q-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: var(--font-size-xs);
    color: var(--text-secondary);
}

.q-legend__dot {
    flex: 0 0 auto;
    width: 10px;
    height: 10px;
    border-radius: 3px;
    background: var(--c, var(--chart-1));
}

.q-legend__dot--line {
    width: 15px;
    height: 3px;
    border-radius: 2px;
}

.q-legend__val {
    margin-left: 4px;
    font-family: var(--font-mono);
    color: var(--text-muted);
}

.q-legend__item--btn {
    padding: 2px 5px;
    border: 0;
    border-radius: var(--radius-xs);
    background: transparent;
    font: inherit;
    color: inherit;
    cursor: pointer;
    transition: background-color var(--timing-fast) var(--ease);
}

    .q-legend__item--btn:hover {
        background: var(--hover-bg);
    }

    .q-legend__item--btn:focus-visible {
        outline: none;
        box-shadow: var(--ring);
    }

.q-legend__item.is-off {
    opacity: .42;
}

    .q-legend__item.is-off .q-legend__dot {
        background: var(--text-faint);
    }


/* ============================================================================
   44.  CHART  ·  FLOATING TOOLTIP
   ----------------------------------------------------------------------------
   For a plot library's external/custom tooltip (Chart.js `external`, a D3
   overlay). The library positions it; we style it and toggle .is-open. Opaque
   surface so a busy plot behind it never bleeds through.
   ============================================================================ */
.q-charttip {
    position: fixed;
    z-index: var(--z-menu);
    min-width: 132px;
    max-width: 264px;
    padding: var(--sp-3);
    border: 1px solid var(--glass-edge-strong);
    border-radius: var(--radius-sm);
    background: var(--surface-5);
    box-shadow: var(--highlight-top), var(--shadow-lg);
    pointer-events: none;
    opacity: 0;
    transform: translateY(2px);
    transition: opacity var(--timing-fast) var(--ease), transform var(--timing-fast) var(--ease-out);
}

    .q-charttip.is-open {
        opacity: 1;
        transform: translateY(0);
    }

.q-charttip__title {
    margin-bottom: 6px;
    font-size: var(--font-size-xxs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-faint);
}

.q-charttip__row {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: var(--font-size-xs);
    color: var(--text-secondary);
}

    .q-charttip__row + .q-charttip__row {
        margin-top: 4px;
    }

.q-charttip__dot {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 2px;
    background: var(--c, var(--chart-1));
}

.q-charttip__val {
    margin-left: auto;
    padding-left: var(--sp-4);
    font-family: var(--font-mono);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}


/* ============================================================================
   45.  SPARKLINE
   ----------------------------------------------------------------------------
   A tiny inline trend for KPI cards and table rows. Stroke follows currentColor,
   so the up/down variants recolour the whole line via one property. Draw into it:
     <span class="q-spark q-spark--up"><svg viewBox="0 0 96 28" preserveAspectRatio="none">
        <polyline class="q-spark__line" points="…"/></svg></span>
   ============================================================================ */
.q-spark {
    display: inline-block;
    width: 96px;
    height: 28px;
    color: var(--chart-1);
    vertical-align: middle;
}

    .q-spark > svg,
    .q-spark > canvas {
        display: block;
        width: 100%;
        height: 100%;
        overflow: visible;
    }

.q-spark--sm {
    width: 64px;
    height: 20px;
}

.q-spark--lg {
    width: 140px;
    height: 40px;
}

.q-spark--up {
    color: var(--success);
}

.q-spark--down {
    color: var(--danger);
}

.q-spark__line {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.q-spark__fill {
    fill: currentColor;
    stroke: none;
    opacity: .12;
}

.q-spark__dot {
    fill: currentColor;
}


/* ============================================================================
   46.  DELTA  ·  standalone trend pill
   ----------------------------------------------------------------------------
   The stat card already has .q-stat__delta, but it's welded to that component.
   This is the same idea, free-standing — usable in a table cell, next to a
   headline number, or in a chart footer. Same success/danger semantics.
     <span class="q-delta q-delta--up q-delta--caret">12.4%</span>
   ============================================================================ */
.q-delta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-semibold);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    white-space: nowrap;
}

    .q-delta svg {
        width: 12px;
        height: 12px;
    }

.q-delta--up {
    color: var(--success);
    background: var(--success-subtle);
}

.q-delta--down {
    color: var(--danger);
    background: var(--danger-subtle);
}

.q-delta--flat {
    color: var(--text-muted);
    background: var(--hover-bg);
}

/* Optional glyph caret (no SVG needed). */
.q-delta--caret::before {
    font-size: 9px;
    line-height: 1;
}

.q-delta--up.q-delta--caret::before {
    content: "\25B2"; /* ▲ */
}

.q-delta--down.q-delta--caret::before {
    content: "\25BC"; /* ▼ */
}

.q-delta--flat.q-delta--caret::before {
    content: "\2013"; /* – */
}

/* Bare: strip the pill for dense inline use inside tables. */
.q-delta--bare {
    padding: 0;
    background: transparent;
    border-radius: 0;
}


/* ============================================================================
   47.  INLINE CODE  ·  .q-code
   ----------------------------------------------------------------------------
   For IDs, IPs, paths, and tokens shown inline in dashboard copy — the founder
   traffic table is full of them. A recessed monospace chip; pairs with the
   existing .q-kbd for keys and .q-mono for runs of data.
   ============================================================================ */
.q-code {
    padding: .12em .42em;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xs);
    background: var(--surface-0);
    color: var(--text-secondary);
    font-family: var(--font-mono);
    font-size: .92em;
    white-space: nowrap;
}


/* ============================================================================
   48.  TOAST ACTION  ·  new element driven by qlynic-ui.js v9
   ----------------------------------------------------------------------------
   QlynicUI.toast(msg, { action: { label, onClick } }) renders this button.
   Everything else the toast needs (__ico / __main / __title / __text / __x)
   already lives in section 10 of qlynic-ui.css.
   ============================================================================ */
.q-toast__action {
    flex: 0 0 auto;
    align-self: center;
    margin-left: var(--sp-1);
    padding: 5px 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--text-primary);
    font-family: var(--font);
    font-size: var(--font-size-xs);
    font-weight: var(--fw-semibold);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--timing-fast) var(--ease), border-color var(--timing-fast) var(--ease);
}

    .q-toast__action:hover {
        background: var(--hover-bg-strong);
        border-color: var(--border-strong);
    }

    .q-toast__action:focus-visible {
        outline: none;
        box-shadow: var(--ring);
    }


/* ============================================================================
   49.  REDUCED MOTION  (scoped to the elements added above)
   ============================================================================ */
@media (prefers-reduced-motion: reduce) {
    .q-charttip,
    .q-legend__item--btn,
    .q-toast__action {
        transition: none;
    }
}

/* ############################################################################
   END OF qlynic-ui.css
   ############################################################################ */
