/* ============================================================================
   TPL DESIGN SYSTEM — central tokens + shared components   (v4: EduSphere direction, light + dark)
   ----------------------------------------------------------------------------
   Single source of truth for the admin design language. Loaded globally by
   resources/views/vendor/adminlte/page.blade.php, followed by tpl-skin.css,
   which re-skins every Bootstrap / AdminLTE / plugin component from these
   tokens. Spec: docs/design-system/README.md.

   TO RE-THEME THE WHOLE PANEL: set --tpl-primary and --tpl-on-primary. A preset
   (public/css/themes/*.css), Superadmin → Appearance → Custom, or a school's own
   brand colour does it for you. Every soft background, border, focus ring and
   hover shade below is derived from --tpl-primary with color-mix(); the hex
   values are fallbacks for older browsers. With nothing set, the panel uses
   the monochrome "Ink" look: --tpl-primary follows --tpl-ink.

   Page-specific blades should use these classes (tpl-card, tpl-btn-primary,
   tpl-chip, ...) and the CSS variables — never hardcode accent hex values.
   All text/background pairs are WCAG 2.2 AA (see the design doc).
   ========================================================================== */

/* ── Fonts (self-hosted, SIL OFL; licences next to the files) ────────────────
   Plus Jakarta Sans = interface, Outfit = headings and figures, JetBrains Mono =
   identifiers. Each family is a variable font split into Latin and Latin-ext;
   the browser only downloads a file when the page uses a character in its range.
   Outfit and JetBrains Mono have no ₹ (U+20B9): their stacks list Plus Jakarta
   Sans next, whose Latin-ext file has it, so ₹ never falls back to a system font.
   Their Latin-ext ranges skip U+20B9, so a ₹ in a heading doesn't fetch a file for nothing. */
@font-face {
    font-family: 'Plus Jakarta Sans';
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url('../fonts/plus-jakarta-sans/plus-jakarta-sans-var-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Plus Jakarta Sans';
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url('../fonts/plus-jakarta-sans/plus-jakarta-sans-var-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Outfit';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/outfit/outfit-var-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Outfit';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/outfit/outfit-var-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20B8, U+20BA-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 100 800;
    font-display: swap;
    src: url('../fonts/jetbrains-mono/jetbrains-mono-var-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 100 800;
    font-display: swap;
    src: url('../fonts/jetbrains-mono/jetbrains-mono-var-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20B8, U+20BA-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ── LIGHT (default) ─────────────────────────────────────────────────────── */
:root {
    color-scheme: light;

    /* Neutral "ink": structure (selected navigation, dark banners, toasts) and,
       unless a preset or school colour is set, the primary too. */
    --tpl-ink: #18181b;
    --tpl-on-ink: #ffffff;

    /* Brand accent — the only thing you normally change (white-label).
       Presets, the custom colour and a school's brand colour set both lines. */
    --tpl-primary: var(--tpl-ink);
    --tpl-on-primary: var(--tpl-on-ink);
    --tpl-primary-2: var(--tpl-primary); /* kept for older blades that reference it */

    /* Derived accent shades (fallbacks for browsers without color-mix) */
    --tpl-primary-hover: #27272a;
    --tpl-primary-deep: #09090b;
    --tpl-primary-ink: var(--tpl-primary); /* accent used as TEXT (links, active tab) */
    --tpl-primary-soft: #f1f0ee;
    --tpl-primary-border: #d3d3d1;
    --tpl-primary-focus: rgba(24, 24, 27, .22);
    --tpl-primary-shadow: rgba(24, 24, 27, .16);
    --tpl-primary-shadow-lg: rgba(24, 24, 27, .24);
    --tpl-accent: var(--tpl-primary);    /* secondary highlight; follows the brand unless a preset sets it */

    /* Surfaces & lines — warm "paper" neutrals */
    --tpl-canvas: #f7f6f3;               /* page background */
    --tpl-surface: #ffffff;              /* cards, inputs, menus */
    --tpl-surface-2: #ffffff;            /* raised: dropdowns, modals, popovers */
    --tpl-bg-soft: #fbfbfa;              /* inset: card footers, addons, input wells */
    --tpl-hover: #f4f3f0;                /* row / item hover */
    --tpl-divider: #f1f0ee;              /* chip fills, skeletons, icon wells */
    --tpl-line: #efefee;                 /* hairlines inside cards */
    --tpl-border: #e7e7e6;               /* card / table / header borders */
    --tpl-border-strong: #d3d3d1;        /* secondary buttons, icon buttons */
    --tpl-control-border: #908e88;       /* inputs — 3.3:1 on white, 3.0:1 on canvas (WCAG 1.4.11) */

    /* Text (all AA on surface and canvas) */
    --tpl-text: #09090b;                 /* titles, key figures        19.9:1 */
    --tpl-text-strong: #27272a;          /* emphasised text            14.9:1 */
    --tpl-text-2: #3f3d39;               /* body text                  10.8:1 */
    --tpl-text-label: #52504b;           /* labels, secondary text      8.0:1 */
    --tpl-text-3: #6b6b73;               /* captions, help, meta        5.3:1 (4.9 on canvas) */
    --tpl-text-muted: #a1a1aa;           /* decorative icons only — never text */
    --tpl-text-disabled: #a1a1aa;        /* disabled controls (exempt from contrast rules) */

    /* Status */
    --tpl-green: #15803d;
    --tpl-green-2: #16a34a;
    --tpl-green-soft: #eef7f1;
    --tpl-green-border: #bfe0ca;
    --tpl-red: #b91c1c;
    --tpl-red-hover: #991b1b;
    --tpl-red-soft: #fcf0ef;
    --tpl-red-border: #f1c4c0;
    --tpl-blue: #1d5fa8;
    --tpl-blue-soft: #eef4fb;
    --tpl-blue-border: #c4d8ee;
    --tpl-violet: #6d47b8;
    --tpl-violet-soft: #f3f0fb;
    --tpl-violet-border: #d9cdf3;
    --tpl-teal: #0b6e74;
    --tpl-teal-soft: #e6f4f4;
    --tpl-teal-border: #b5dcdd;
    --tpl-amber: #b45309;
    --tpl-amber-soft: #fdf5e7;
    --tpl-amber-border: #f0d6a8;
    --tpl-haldi: #fec92f;                /* highlight fill — never text on white */

    /* Solid tile colours (KPI icon squares, avatars) — white icon on top ≥4.5:1 */
    --tpl-tile-blue: #2f6fd6;
    --tpl-tile-green: #16875a;
    --tpl-tile-amber: #c2620a;
    --tpl-tile-violet: #7045c9;
    --tpl-tile-red: #d0342c;
    --tpl-tile-teal: #0f7f86;
    --tpl-tile-slate: #52525b;

    /* Chart series (categorical, fixed order — never cycled). Validated with the
       dataviz checks against this surface: CVD ΔE ≥ 8.4 adjacent, normal-vision
       ΔE ≥ 19.3, lightness band and chroma pass in both modes. Slots 3–5 are under
       3:1 on white, so multi-series charts keep a legend and tooltips. Green and
       red stay reserved for status (use --tpl-tile-* for paid/present etc.). */
    --tpl-chart-1: #2a78d6;              /* blue */
    --tpl-chart-2: #eb6834;              /* orange */
    --tpl-chart-3: #1baf7a;              /* aqua */
    --tpl-chart-4: #eda100;              /* yellow */
    --tpl-chart-5: #e87ba4;              /* magenta */
    --tpl-chart-6: #4a3aa7;              /* violet */
    --tpl-chart-7: #008300;              /* green — slots 7–8 only for charts with 7+ categories */
    --tpl-chart-8: #e34948;              /* red   (7↔8 is in the CVD warn band: keep legends + gaps) */
    /* Ordered categories (difficulty bands, tiers): one hue, light → dark.
       Documented blue ramp steps 250–600: the lightest clears 2:1 on white and
       the darkest clears 2:1 on the dark surface, so one set serves both modes. */
    --tpl-seq-1: #86b6ef;
    --tpl-seq-2: #5598e7;
    --tpl-seq-3: #2a78d6;
    --tpl-seq-4: #1c5cab;
    --tpl-seq-5: #184f95;
    --tpl-chart-grid: var(--tpl-line);
    --tpl-chart-axis: var(--tpl-text-3);

    /* Sidebar — dark variant (Appearance → "Dark"); the light variant is
       defined in tpl-skin.css from the neutrals above. */
    --tpl-sidebar-bg: #111113;
    --tpl-sidebar-hover: rgba(255, 255, 255, .05);
    --tpl-sidebar-active-bg: #f4f4f5;
    --tpl-sidebar-active-text: #09090b;
    --tpl-sidebar-text: #a1a1aa;
    --tpl-sidebar-text-strong: #fafafa;
    --tpl-sidebar-muted: #8b8b93;
    --tpl-sidebar-line: rgba(255, 255, 255, .07);
    --tpl-sidebar-indicator: #a1a1aa;

    /* Layout */
    --tpl-sidebar-width: 260px;          /* tpl-skin.css maps AdminLTE's 250px rules onto this */
    --tpl-header-h: calc(3.5rem + 1px); /* AdminLTE's own height (57px); its layout sums use it */
    --tpl-container: 1440px;
    --tpl-gutter: 24px;                  /* page padding; 16 on phones */
    --tpl-control-h: 42px;               /* inputs, selects, Select2 (44 on phones) */
    --tpl-space-1: 4px;                  /* 4px spacing scale */
    --tpl-space-2: 8px;
    --tpl-space-3: 12px;
    --tpl-space-4: 16px;
    --tpl-space-5: 20px;
    --tpl-space-6: 24px;
    --tpl-space-7: 32px;
    --tpl-space-8: 48px;

    /* Type */
    --tpl-font: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto, 'Noto Sans', 'Helvetica Neue', Arial, sans-serif;
    --tpl-font-heading: 'Outfit', 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto, 'Noto Sans', Arial, sans-serif;
    --tpl-font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, Consolas, 'Plus Jakarta Sans', 'Liberation Mono', monospace;
    --tpl-fs-xs: .6875rem;    /* 11 — pills, overlines (the floor) */
    --tpl-fs-sm: .75rem;      /* 12 — captions */
    --tpl-fs-label: .78125rem;/* 12.5 — labels, table headers */
    --tpl-fs-base: .875rem;   /* 14 — body, table cells */
    --tpl-fs-md: 1.0625rem;   /* 17 — card / section titles */
    --tpl-fs-lg: 1.5rem;      /* 24 — page titles */
    --tpl-fs-kpi: 1.625rem;   /* 26 — KPI figures */
    --tpl-fs-display: 2rem;   /* 32 — auth and empty-state heroes */
    --tpl-lh-body: 1.55;
    --tpl-tracking-heading: -.02em;
    --tpl-tracking-title: -.025em;
    --tpl-tracking-caps: .04em;

    /* Shape — the names keep their v3 roles; values follow the v4 scale */
    --tpl-radius-xs: 6px;     /* badges, small chips, checkboxes */
    --tpl-radius-sm: 10px;    /* buttons, inputs, menu items */
    --tpl-radius: 14px;       /* cards, tables, header */
    --tpl-radius-lg: 16px;    /* modals, large panels */
    --tpl-radius-xl: 20px;    /* sheets, auth card */
    --tpl-radius-pill: 999px; /* status pills, avatars, switches */

    /* Depth — hairline + soft shadow; nothing coloured */
    --tpl-shadow-1: 0 1px 2px rgba(0, 0, 0, .05);
    --tpl-shadow-2: 0 8px 24px -8px rgba(15, 15, 15, .12), 0 1px 2px rgba(0, 0, 0, .04);
    --tpl-shadow-3: 0 20px 48px -12px rgba(15, 15, 15, .18), 0 2px 6px rgba(0, 0, 0, .05);
    --tpl-card-shadow: var(--tpl-shadow-1);
    --tpl-focus-ring: 0 0 0 3px var(--tpl-primary-focus);

    /* Motion */
    --tpl-ease: cubic-bezier(.2, 0, 0, 1);
    --tpl-dur: 180ms;

    /* Solid since v2: the gradient look read as dated. Blades that paint with
       var(--tpl-grad) now get a flat accent fill. */
    --tpl-grad: linear-gradient(0deg, var(--tpl-primary), var(--tpl-primary));
}

/* Modern browsers: derive accent shades from --tpl-primary so a single
   variable change re-themes soft backgrounds, borders and shadows too. */
@supports (color: color-mix(in srgb, red 50%, white)) {
    :root {
        --tpl-primary-hover: color-mix(in srgb, var(--tpl-primary) 86%, #000000);
        --tpl-primary-deep: color-mix(in srgb, var(--tpl-primary) 72%, #000000);
        --tpl-primary-soft: color-mix(in srgb, var(--tpl-primary) 8%, #ffffff);
        --tpl-primary-border: color-mix(in srgb, var(--tpl-primary) 26%, #ffffff);
        --tpl-primary-focus: color-mix(in srgb, var(--tpl-primary) 24%, transparent);
        --tpl-primary-shadow: color-mix(in srgb, var(--tpl-primary) 16%, transparent);
        --tpl-primary-shadow-lg: color-mix(in srgb, var(--tpl-primary) 24%, transparent);
    }
}
/* A bright version of the primary for accents on dark surfaces. */
@supports (color: oklch(from red l c h)) {
    :root {
        --tpl-sidebar-indicator: oklch(from var(--tpl-primary) .8 calc(c * 1.4) h);
    }
}

/* ── DARK ────────────────────────────────────────────────────────────────────
   Toggled per browser from the header (sun/moon); the default comes from
   Superadmin → Appearance → Dark mode. Set on <html data-theme="dark">.
   Zinc neutrals (the warm paper tones turn muddy in the dark). */
html[data-theme="dark"] {
    color-scheme: dark;

    --tpl-ink: #fafafa;
    --tpl-on-ink: #09090b;

    --tpl-primary-hover: #e4e4e7;
    --tpl-primary-ink: var(--tpl-primary);
    --tpl-primary-soft: #232326;
    --tpl-primary-border: #3a3a3e;
    --tpl-primary-deep: #ffffff;

    --tpl-canvas: #09090b;
    --tpl-surface: #141416;
    --tpl-surface-2: #1c1c1f;
    --tpl-bg-soft: #18181b;
    --tpl-hover: #1f1f23;
    --tpl-divider: #27272a;
    --tpl-line: #232326;
    --tpl-border: #2c2c30;
    --tpl-border-strong: #45454a;
    --tpl-control-border: #6a6a70;       /* 3.4:1 on dark surface */

    --tpl-text: #fafafa;
    --tpl-text-strong: #e4e4e7;
    --tpl-text-2: #d4d4d8;
    --tpl-text-label: #b4b4bb;
    --tpl-text-3: #a1a1aa;
    --tpl-text-muted: #71717a;
    --tpl-text-disabled: #5b5b63;

    --tpl-green: #4ade80;
    --tpl-green-soft: rgba(34, 197, 94, .10);
    --tpl-green-border: rgba(34, 197, 94, .32);
    --tpl-red: #f87171;
    --tpl-red-soft: rgba(239, 68, 68, .10);
    --tpl-red-border: rgba(239, 68, 68, .32);
    --tpl-blue: #7ab8f5;
    --tpl-blue-soft: rgba(96, 165, 250, .10);
    --tpl-blue-border: rgba(96, 165, 250, .32);
    --tpl-violet: #b8a2f0;
    --tpl-violet-soft: rgba(167, 139, 250, .10);
    --tpl-violet-border: rgba(167, 139, 250, .32);
    --tpl-teal: #5fcfcf;
    --tpl-teal-soft: rgba(45, 212, 191, .10);
    --tpl-teal-border: rgba(45, 212, 191, .32);
    --tpl-amber: #fbbf24;
    --tpl-amber-soft: rgba(245, 158, 11, .10);
    --tpl-amber-border: rgba(245, 158, 11, .32);

    --tpl-sidebar-bg: #0f0f11;

    /* Chart series stepped for the dark surface (same hues, validated as a set) */
    --tpl-chart-1: #3987e5;
    --tpl-chart-2: #d95926;
    --tpl-chart-3: #199e70;
    --tpl-chart-4: #c98500;
    --tpl-chart-5: #d55181;
    --tpl-chart-6: #9085e9;
    --tpl-chart-7: #008300;
    --tpl-chart-8: #e66767;

    --tpl-shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
    --tpl-shadow-2: 0 8px 24px -8px rgba(0, 0, 0, .6), 0 1px 2px rgba(0, 0, 0, .4);
    --tpl-shadow-3: 0 20px 48px -12px rgba(0, 0, 0, .8), 0 2px 6px rgba(0, 0, 0, .4);
}
@supports (color: color-mix(in srgb, red 50%, white)) {
    html[data-theme="dark"] {
        --tpl-primary-hover: color-mix(in srgb, var(--tpl-primary) 86%, var(--tpl-canvas));
        --tpl-primary-soft: color-mix(in srgb, var(--tpl-primary) 16%, #141416);
        --tpl-primary-border: color-mix(in srgb, var(--tpl-primary) 38%, #141416);
    }
}
/* A coloured brand is darkened into a readable text accent on dark surfaces;
   the monochrome default (primary = ink, already light) needs no shift. */
@supports (color: oklch(from red l c h)) {
    html[data-theme="dark"] {
        --tpl-primary-ink: oklch(from var(--tpl-primary) max(l, .74) calc(c * 1.15) h);
        --tpl-primary-deep: oklch(from var(--tpl-primary) .84 c h);
    }
}

/* ============================================================================
   COMPONENTS
   ========================================================================== */

/* ── Page header helpers ── */
.tpl-page-head { row-gap: 10px; }
.tpl-head-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* ── Buttons ── */
.tpl-btn-primary {
    background: var(--tpl-primary);
    color: var(--tpl-on-primary) !important;
    border: 1px solid var(--tpl-primary);
    font-weight: 600;
    border-radius: var(--tpl-radius-sm);
    padding: 7.5px 16px;
    box-shadow: var(--tpl-shadow-1);
    transition: background-color .15s var(--tpl-ease), border-color .15s var(--tpl-ease), box-shadow .15s var(--tpl-ease);
}
.tpl-btn-primary:hover:not(:disabled) { background: var(--tpl-primary-hover); border-color: var(--tpl-primary-hover); }
.tpl-btn-primary:focus-visible { outline: 0; box-shadow: var(--tpl-focus-ring); }
.tpl-btn-primary:disabled { opacity: .6; }
.tpl-btn-ghost {
    background: var(--tpl-surface);
    color: var(--tpl-text-2) !important;
    border: 1px solid var(--tpl-border-strong);
    border-radius: var(--tpl-radius-sm);
    padding: 7.5px 14px;
    font-weight: 550;
    transition: background-color .15s var(--tpl-ease), border-color .15s var(--tpl-ease);
}
.tpl-btn-ghost:hover { background: var(--tpl-hover); border-color: var(--tpl-control-border); color: var(--tpl-text) !important; }
.tpl-btn-ghost:focus-visible { outline: 0; box-shadow: var(--tpl-focus-ring); }
.tpl-btn-wa {
    background: var(--tpl-green-soft);
    color: var(--tpl-green) !important;
    border: 1px solid var(--tpl-green-soft);
    font-weight: 600;
    border-radius: var(--tpl-radius-sm);
    transition: background-color .15s ease, border-color .15s ease;
}
.tpl-btn-wa i { margin-right: 3px; }
.tpl-btn-wa:hover:not(.disabled) { background: var(--tpl-green-soft); border-color: var(--tpl-green-border); color: var(--tpl-green) !important; }
.tpl-btn-wa.disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
/* Solid accent (green tile) — a secondary CTA distinct from the primary. */
.tpl-btn-accent {
    background: var(--tpl-tile-green);
    color: #fff !important;
    border: none;
    font-weight: 600;
    border-radius: var(--tpl-radius-sm);
    padding: 8px 16px;
    transition: filter .15s ease, box-shadow .15s ease;
}
.tpl-btn-accent:hover:not(:disabled) { filter: brightness(1.06); box-shadow: var(--tpl-shadow-2); }
.tpl-btn-accent:disabled { opacity: .7; }

/* ── Cards ──
   Static containers stay still on hover (movement on non-interactive surfaces
   is noise). Clickable cards — an <a class="tpl-card"> or .is-clickable — get
   a calm border + shadow response. */
.tpl-card {
    background: var(--tpl-surface);
    border: 1px solid var(--tpl-border);
    border-radius: var(--tpl-radius);
    overflow: hidden;
    transition: box-shadow .18s var(--tpl-ease), border-color .18s var(--tpl-ease);
}
a.tpl-card:hover, .tpl-card.is-clickable:hover { border-color: var(--tpl-border-strong); box-shadow: var(--tpl-shadow-2); }
.tpl-card.no-hover:hover { border-color: var(--tpl-border); box-shadow: none; }
.tpl-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 14px 20px;
    border-bottom: 1px solid var(--tpl-line);
}
.tpl-card-title {
    font-family: var(--tpl-font-heading);
    font-weight: 650;
    color: var(--tpl-text);
    font-size: var(--tpl-fs-md);
    letter-spacing: -.005em;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
}
.tpl-card-title i { color: var(--tpl-text-muted); font-size: 14px; }
.tpl-card-body { padding: 20px; }
.tpl-card-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
/* Form-card footer: right-aligned action row separated by a hairline. */
.tpl-card-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid var(--tpl-line);
}

/* Side help panel: bulleted tips for form pages (fills the empty column). */
.tpl-aside-title {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 700;
    color: var(--tpl-text);
    font-size: .95rem;
    margin: 0 0 12px;
}
.tpl-tips { list-style: none; margin: 0; padding: 0; }
.tpl-tips li {
    position: relative;
    padding: 8px 0 8px 20px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--tpl-text-2);
    border-bottom: 1px solid var(--tpl-line);
}
.tpl-tips li:last-child { border-bottom: 0; }
.tpl-tips li::before {
    content: '';
    position: absolute;
    left: 2px;
    top: 14px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--tpl-primary);
}
.tpl-tips li strong { color: var(--tpl-text); font-weight: 600; }

/* ── Soft chips ── */
/* Same translucent "glass" pill as .badge: tint, same-hue border, strong text. */
.tpl-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--tpl-fs-xs);
    font-weight: 650;
    line-height: 1.5;
    border: 1px solid var(--tpl-border);
    border-radius: var(--tpl-radius-pill);
    padding: 2px 9px;
    white-space: nowrap;
    background: var(--tpl-divider);
    color: var(--tpl-text-label);
}
.tpl-chip.is-green { background: var(--tpl-green-soft); border-color: var(--tpl-green-border); color: var(--tpl-green); }
.tpl-chip.is-red { background: var(--tpl-red-soft); border-color: var(--tpl-red-border); color: var(--tpl-red); }
.tpl-chip.is-blue { background: var(--tpl-blue-soft); border-color: var(--tpl-blue-border); color: var(--tpl-blue); }
.tpl-chip.is-violet { background: var(--tpl-violet-soft); border-color: var(--tpl-violet-border); color: var(--tpl-violet); }
.tpl-chip.is-amber { background: var(--tpl-amber-soft); border-color: var(--tpl-amber-border); color: var(--tpl-amber); }
.tpl-chip.is-indigo { background: var(--tpl-primary-soft); border-color: var(--tpl-primary-border); color: var(--tpl-primary-ink); }
.tpl-chip.is-muted { background: var(--tpl-divider); border-color: var(--tpl-border); color: var(--tpl-text-3); }
/* x-ui.status-pill: short statuses in capitals with a leading dot */
.tpl-chip.is-status { text-transform: uppercase; letter-spacing: var(--tpl-tracking-caps); }
.tpl-chip .tpl-chip-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 6px; }

/* ── Filter pills ── */
.tpl-pill {
    border: 1px solid var(--tpl-border);
    background: var(--tpl-surface);
    color: var(--tpl-text-2);
    border-radius: 999px;
    padding: 5px 14px;
    font-size: var(--tpl-fs-label);
    font-weight: 550;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.tpl-pill:hover { background: var(--tpl-divider); }
.tpl-pill.active { background: var(--tpl-primary); border-color: var(--tpl-primary); color: var(--tpl-on-primary); }
.tpl-pill-count {
    display: inline-block;
    background: var(--tpl-divider);
    border-radius: 999px;
    padding: 0 7px;
    font-size: 11px;
    margin-left: 4px;
}
.tpl-pill.active .tpl-pill-count { background: color-mix(in srgb, var(--tpl-on-primary) 22%, transparent); }

/* ── Selectable option tiles ──
   A checkbox/radio rendered as a bordered tile that highlights when checked.
   The real input stays in the DOM (hidden but focusable), so no JS is involved
   and keyboard/screen-reader behaviour is unchanged.

   <div class="tpl-opts tpl-opts-2">
     <label class="tpl-opt">
       <input type="checkbox" name="…" value="…">
       <span class="tpl-opt-box">
         <i class="fas fa-camera"></i>
         <span class="tpl-opt-text"><strong>Title</strong><small>Hint</small></span>
         <i class="fas fa-check tpl-opt-tick"></i>
       </span>
     </label>
   </div> */
.tpl-opts { display: grid; grid-template-columns: 1fr; gap: 10px; }
.tpl-opts-2 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.tpl-opts-3 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

.tpl-opt { display: block; margin: 0; cursor: pointer; }
/* Visually hidden but still focusable and exposed to assistive tech. */
.tpl-opt input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    margin: 0;
}
.tpl-opt-box {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border: 1px solid var(--tpl-border);
    border-radius: var(--tpl-radius-sm);
    background: var(--tpl-surface);
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.tpl-opt-box > i:first-child { font-size: 16px; color: var(--tpl-text-muted); width: 18px; text-align: center; }
.tpl-opt-text { flex: 1 1 auto; min-width: 0; }
.tpl-opt-text strong { display: block; font-size: 13px; font-weight: 600; color: var(--tpl-text); }
.tpl-opt-text small { display: block; font-size: 11.5px; color: var(--tpl-text-3); }
.tpl-opt-tick { font-size: 12px; color: var(--tpl-primary-ink); opacity: 0; transition: opacity .15s ease; }

.tpl-opt:hover .tpl-opt-box { border-color: var(--tpl-border-strong); }
.tpl-opt input:checked + .tpl-opt-box {
    border-color: var(--tpl-primary-border);
    background: var(--tpl-primary-soft);
}
.tpl-opt input:checked + .tpl-opt-box > i:first-child { color: var(--tpl-primary-ink); }
.tpl-opt input:checked + .tpl-opt-box .tpl-opt-tick { opacity: 1; }
.tpl-opt input:focus-visible + .tpl-opt-box { box-shadow: 0 0 0 3px var(--tpl-primary-focus); }
.tpl-opt input:disabled + .tpl-opt-box { opacity: .55; cursor: not-allowed; }

/* ── Ghost icon buttons ── */
.tpl-icon-btn {
    width: 30px;
    height: 30px;
    border: none;
    background: transparent;
    border-radius: 6px;
    color: var(--tpl-text-muted);
    font-size: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
.tpl-icon-btn:hover { background: var(--tpl-primary-soft); color: var(--tpl-primary-ink); }
.tpl-icon-btn.is-danger:hover { background: var(--tpl-red-soft); color: var(--tpl-red); }

/* ── Icon squares ── */
.tpl-ico {
    width: 38px;
    height: 38px;
    border-radius: var(--tpl-radius);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .95rem;
    flex-shrink: 0;
    background: var(--tpl-primary-soft);
    color: var(--tpl-primary-ink);
}
.tpl-ico.is-green { background: var(--tpl-green-soft); color: var(--tpl-green); }
.tpl-ico.is-blue { background: var(--tpl-blue-soft); color: var(--tpl-blue); }
.tpl-ico.is-violet { background: var(--tpl-violet-soft); color: var(--tpl-violet); }
.tpl-ico.is-amber { background: var(--tpl-amber-soft); color: var(--tpl-amber); }
.tpl-ico.is-red { background: var(--tpl-red-soft); color: var(--tpl-red); }
.tpl-ico.is-gray { background: var(--tpl-divider); color: var(--tpl-text-2); }

/* ── Switches ── */
.tpl-switch { position: relative; display: inline-block; width: 38px; height: 21px; flex-shrink: 0; cursor: pointer; margin: 0; }
.tpl-switch input { opacity: 0; width: 0; height: 0; }
.tpl-switch .slider {
    position: absolute;
    inset: 0;
    background: var(--tpl-border-strong);
    border-radius: 999px;
    transition: background-color .15s ease;
}
.tpl-switch .slider:before {
    content: '';
    position: absolute;
    height: 17px;
    width: 17px;
    left: 2px;
    top: 2px;
    background: var(--tpl-surface);
    border-radius: 50%;
    transition: transform .15s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
}
.tpl-switch input:checked + .slider { background: var(--tpl-primary); }
.tpl-switch input:checked + .slider:before { transform: translateX(17px); }
.tpl-switch input:disabled + .slider { opacity: .5; cursor: not-allowed; }

/* ── Form fields (scope with .tpl-form) ── */
.tpl-form label { font-size: var(--tpl-fs-label); font-weight: 550; color: var(--tpl-text-label); margin-bottom: 6px; }
.tpl-form .form-control, .tpl-form .custom-select {
    border-radius: var(--tpl-radius-sm);
    border-color: var(--tpl-border-strong);
}
.tpl-form .form-control:focus, .tpl-form .custom-select:focus {
    border-color: var(--tpl-primary-border);
    box-shadow: 0 0 0 3px var(--tpl-primary-focus);
}

/* ── Compact filter bar (add .tpl-filter alongside .tpl-form) ──
   Smaller muted labels + compact controls/buttons for filter rows. */
.tpl-filter label {
    font-size: 12.5px;
    font-weight: 550;
    text-transform: none;
    letter-spacing: 0;
    color: var(--tpl-text-label);
    margin-bottom: 4px;
}
.tpl-filter .form-control,
.tpl-filter .custom-select,
.tpl-filter select.form-control {
    height: calc(1.4em + .5rem + 2px);
    padding: .25rem .55rem;
    font-size: 13px;
}
.tpl-filter .btn { padding: 6px 14px; font-size: 13px; }
.tpl-filter .input-group-text { padding: .25rem .5rem; }

/* ── Toolbar (search + pills) ── */
.tpl-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    justify-content: space-between;
    background: var(--tpl-surface);
    border: 1px solid var(--tpl-border);
    border-radius: var(--tpl-radius);
    padding: 10px 12px;
}
/* `space-between` above assumes TWO groups (e.g. search left, actions right).
   A toolbar whose only children are bare pills gets them flung to opposite
   edges with the middle ones stranded — add `is-start` to keep them clustered. */
.tpl-toolbar.is-start { justify-content: flex-start; }

/* ── Soft banners ── */
.tpl-banner {
    background: var(--tpl-primary-soft);
    border: 1px solid var(--tpl-primary-border);
    color: var(--tpl-primary-ink);
    border-radius: var(--tpl-radius);
    padding: 10px 14px;
    font-size: 13.5px;
}
.tpl-banner i { margin-right: 6px; }
.tpl-banner.is-warning {
    background: var(--tpl-amber-soft);
    border-color: var(--tpl-amber-border);
    color: var(--tpl-amber);
}
.tpl-banner.is-success {
    background: var(--tpl-green-soft);
    border-color: var(--tpl-green-border);
    color: var(--tpl-green);
}
.tpl-banner.is-danger {
    background: var(--tpl-red-soft);
    border-color: var(--tpl-red-border);
    color: var(--tpl-red);
}

/* ── Tables (pair with .table inside a .tpl-card) ──
   v2: a quiet header band and horizontal rules only. The old indigo band with
   a vertical rule on every cell read like a spreadsheet, not a product. */
.tpl-table { margin-bottom: 0; }
.tpl-table thead th {
    background: transparent;
    color: var(--tpl-text-strong);
    font-size: var(--tpl-fs-label);
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
    border-top: 0;
    border-bottom: 1px solid var(--tpl-border);
    border-right: 0;
    padding: 10px 16px;
    white-space: nowrap;
    vertical-align: middle;
}
.tpl-table tbody td {
    padding: 12px 16px;
    border-top: 0;
    border-bottom: 1px solid var(--tpl-line);
    border-right: 0;
    vertical-align: middle;
    font-size: var(--tpl-fs-base);
    color: var(--tpl-text-2);
}
.tpl-table tbody tr:last-child td { border-bottom: 0; }
.tpl-table .tpl-td-num {
    width: 52px;
    text-align: center;
    color: var(--tpl-text-3);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.tpl-table tbody tr { transition: background-color .12s ease; }
.tpl-table tbody tr:hover { background: var(--tpl-hover); }

/* ── Empty state ── */
/* ── Empty / error / loading states (x-ui.empty-state, x-ui.error-state) ── */
.tpl-empty { text-align: center; padding: 48px 20px; }
.tpl-empty-ico {
    width: 52px;
    height: 52px;
    margin: 0 auto 14px;
    border-radius: var(--tpl-radius);
    background: var(--tpl-divider);
    border: 1px solid var(--tpl-border);
    color: var(--tpl-text-label);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
}
.tpl-empty-title { font-family: var(--tpl-font-heading); font-size: var(--tpl-fs-md); font-weight: 650; letter-spacing: var(--tpl-tracking-heading); color: var(--tpl-text); }
.tpl-empty-sub { font-size: var(--tpl-fs-label); color: var(--tpl-text-3); max-width: 420px; margin: 4px auto 0; }
.tpl-empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 16px; }
.tpl-empty.is-compact { padding: 24px 16px; }
.tpl-empty.is-error .tpl-empty-ico { background: var(--tpl-red-soft); border-color: var(--tpl-red-border); color: var(--tpl-red); }
/* Skeleton placeholders while AJAX content loads */
.tpl-skeleton {
    display: block;
    height: 12px;
    border-radius: var(--tpl-radius-xs);
    background: linear-gradient(90deg, var(--tpl-divider) 0%, var(--tpl-hover) 50%, var(--tpl-divider) 100%);
    background-size: 200% 100%;
    animation: tpl-shimmer 1.4s ease-in-out infinite;
}
.tpl-skeleton + .tpl-skeleton { margin-top: 10px; }
.tpl-skeleton.is-title { height: 18px; width: 40%; }
.tpl-skeleton.is-short { width: 60%; }
.tpl-skeleton.is-block { height: 96px; border-radius: var(--tpl-radius-sm); }
.tpl-skeleton.is-circle { width: 36px; height: 36px; border-radius: 50%; }
@keyframes tpl-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .tpl-skeleton { animation: none; } }

/* ── x-ui.page-header ── */
.tpl-page-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--tpl-space-3); }
.tpl-page-header-main { min-width: 0; }
.tpl-page-header .breadcrumb { margin-bottom: 6px; }
.tpl-page-title { font-family: var(--tpl-font-heading); font-size: var(--tpl-fs-lg); font-weight: 650; letter-spacing: var(--tpl-tracking-title); line-height: 1.25; color: var(--tpl-text); margin: 0; }
.tpl-page-desc { font-size: var(--tpl-fs-base); color: var(--tpl-text-3); margin: 4px 0 0; max-width: 720px; }
.tpl-page-header .tpl-head-actions { margin-left: auto; }
.tpl-page-tabs { margin-top: var(--tpl-space-4); }
@media (max-width: 575.98px) {
    .tpl-page-title { font-size: 1.25rem; }
    .tpl-page-header .tpl-head-actions { margin-left: 0; width: 100%; }
}

/* ── x-ui.module-header / x-ui.module-tab: a module's title block + section tabs ── */
.tpl-module-head { padding-top: var(--tpl-space-4); margin-bottom: var(--tpl-space-6); }
.tpl-module-head .tpl-page-header { margin-bottom: var(--tpl-space-4); }
.tpl-mtabs { display: flex; align-items: stretch; border-bottom: 1px solid var(--tpl-border); }
.tpl-mtabs-list { display: flex; flex-wrap: nowrap; align-items: stretch; gap: 0 var(--tpl-space-5); flex: 1 1 auto; min-width: 0; overflow: hidden; }
.tpl-mtabs-more { flex: 0 0 auto; display: flex; align-items: stretch; margin-left: var(--tpl-space-4); }
.tpl-mtabs-more[hidden] { display: none; }
.tpl-mtab {
    position: relative;
    display: inline-flex; align-items: center; gap: 7px;
    padding: 10px 2px 11px;
    font-size: var(--tpl-fs-base); font-weight: 550; white-space: nowrap;
    color: var(--tpl-text-3); text-decoration: none !important;
}
.tpl-mtab i { font-size: 13px; color: inherit; opacity: .85; }
.tpl-mtab:hover { color: var(--tpl-text); }
.tpl-mtab.active { color: var(--tpl-text); font-weight: 650; }
.tpl-mtab.active::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; border-radius: 2px 2px 0 0; background: var(--tpl-primary); }
.tpl-mtab.dropdown-toggle::after { display: none; }
.tpl-mtab.dropdown-toggle.active::after { display: block; content: ''; border: 0; margin: 0; vertical-align: 0; }
.tpl-mtab:focus-visible { outline: 2px solid var(--tpl-primary); outline-offset: -2px; border-radius: var(--tpl-radius-xs); }
.tpl-mtabs-more .dropdown-item.active { background: var(--tpl-primary-soft); color: var(--tpl-primary-deep); }
.tpl-mtabs-more .dropdown-item i { width: 18px; text-align: center; margin-right: 6px; }
@media (pointer: coarse) { .tpl-mtab { min-height: 44px; } }

/* ── x-ui.person: avatar + name + meta line + identifier ── */
.tpl-person { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.tpl-person-avatar {
    width: 36px; height: 36px; flex: 0 0 36px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--tpl-divider);
    border: 1px solid var(--tpl-border);
    color: var(--tpl-text-label);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 12px; font-weight: 700;
}
.tpl-person.is-sm .tpl-person-avatar { width: 28px; height: 28px; flex-basis: 28px; font-size: 11px; }
.tpl-person-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.tpl-person-name { color: var(--tpl-text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
a.tpl-person:hover .tpl-person-name { text-decoration: underline; text-underline-offset: 2px; }
.tpl-person-meta { font-size: var(--tpl-fs-sm); color: var(--tpl-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-id { font-family: var(--tpl-font-mono); font-size: .8125rem; letter-spacing: -.01em; }

/* ── x-ui.stat-card ── */
.tpl-stat { display: flex; flex-direction: column; gap: 6px; height: 100%; padding: var(--tpl-space-5); background: var(--tpl-surface); border: 1px solid var(--tpl-border); border-radius: var(--tpl-radius); box-shadow: var(--tpl-card-shadow); color: inherit; }
a.tpl-stat:hover { border-color: var(--tpl-border-strong); box-shadow: var(--tpl-shadow-2); color: inherit; text-decoration: none; }
.tpl-stat-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.tpl-stat-label { font-size: var(--tpl-fs-label); font-weight: 600; color: var(--tpl-text-label); }
.tpl-stat-value { font-family: var(--tpl-font-heading); font-size: var(--tpl-fs-kpi); font-weight: 650; letter-spacing: -.02em; line-height: 1.15; color: var(--tpl-text); font-variant-numeric: tabular-nums; }
.tpl-stat-foot { font-size: var(--tpl-fs-sm); color: var(--tpl-text-3); }

/* ── x-ui.filter-bar: inline on desktop; a collapsible panel on phones ── */
.tpl-filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--tpl-space-3); }
.tpl-filter-bar > .form-group { margin-bottom: 0; min-width: 160px; flex: 1 1 180px; }
.tpl-filter-bar .tpl-filter-actions { display: flex; gap: 8px; margin-left: auto; }
.tpl-filter-toggle { display: none; }
@media (max-width: 767.98px) {
    .tpl-filter-toggle { display: inline-flex; }
    .tpl-filter-bar:not(.is-open) > :not(.tpl-filter-toggle) { display: none; }
    .tpl-filter-bar > .form-group { flex-basis: 100%; }
    .tpl-filter-bar .tpl-filter-actions { width: 100%; margin-left: 0; }
    .tpl-filter-bar .tpl-filter-actions .btn { flex: 1; }
}

/* ── Card grid ── */
.tpl-grid-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
    gap: 14px;
}

/* ── Design/template preview cards ──
   The shelf card used by the Templates library and the ID Cards → Card Designs
   page: a large preview box (saved thumbnail, or the design's own markup in a
   lazy iframe) over a footer of name + chip + icon-only actions.
   Lived only in certificates/templates/index.blade.php until a second page
   needed it; identical rules still shipped there are harmless overrides. */
.tpl-manage-card {
    background: var(--tpl-surface);
    border: 1px solid var(--tpl-border);
    border-radius: 10px;
    overflow: hidden;
    transition: box-shadow .18s ease, border-color .18s ease;
}
.tpl-manage-card:hover { border-color: var(--tpl-primary-border); box-shadow: var(--tpl-shadow-2); }

.tpl-preview-box {
    height: 280px;
    overflow: hidden;
    background: var(--tpl-bg-soft);
    position: relative;
}
.tpl-preview-box .lazy-iframe { width: 100%; height: 100%; border: none; pointer-events: none; }

.tpl-designer-badge {
    position: absolute;
    top: 8px; right: 8px; z-index: 2;
    width: 24px; height: 24px;
    border-radius: 999px;
    background: var(--tpl-primary-soft);
    color: var(--tpl-primary-ink);
    font-size: 11px;
    display: flex; align-items: center; justify-content: center;
}

.hover-zoom-icon {
    position: absolute; inset: 0; z-index: 3;
    display: flex; align-items: center; justify-content: center;
    opacity: 0;
    transition: opacity .18s ease;
    pointer-events: none;
    background: rgba(17, 24, 39, .18);
}
.hover-zoom-icon i { font-size: 2rem; color: #fff; filter: drop-shadow(0 2px 4px rgba(0,0,0,.5)); }
.tpl-manage-card:hover .hover-zoom-icon { opacity: 1; }

.thumbnail-inherited-badge {
    position: absolute; bottom: 8px; left: 8px; z-index: 1;
    font-size: var(--tpl-fs-xs);
    background: rgba(17, 24, 39, .65);
    color: #fff;
}

.tpl-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 12px;
    border-top: 1px solid var(--tpl-line);
    background: var(--tpl-surface);
}
.tpl-card-name { font-size: .87rem; font-weight: 600; color: var(--tpl-text); }
.tpl-card-meta { font-size: .72rem; color: var(--tpl-text-3); }
.tpl-card-actions { display: flex; gap: 2px; flex-shrink: 0; }

.tpl-type-chip {
    display: inline-block;
    font-size: .68rem;
    border-radius: 999px;
    padding: 1px 8px;
    margin-top: 2px;
}
.tpl-type-chip.is-student { background: var(--tpl-green-soft); color: var(--tpl-green); }
.tpl-type-chip.is-staff { background: var(--tpl-blue-soft); color: var(--tpl-blue); }
.tpl-type-chip.is-muted { background: var(--tpl-divider); color: var(--tpl-text-3); }

/* ── Mobile polish ── */
@media (max-width: 575.98px) {
    .tpl-head-actions { width: 100%; }
    .tpl-head-actions .btn { flex: 1 1 auto; text-align: center; }
}

/* ── View toggle (list/grid segmented control) ──
   Pair with <x-tpl.view-toggle storage-key="..." target="#..." />.
   Hidden on mobile (cards are forced there via tpl-table-stack). */
.tpl-view-toggle {
    display: inline-flex;
    border: 1px solid var(--tpl-border-strong);
    border-radius: var(--tpl-radius-sm);
    overflow: hidden;
    background: var(--tpl-surface);
}
.tpl-view-toggle .tpl-vt-btn {
    border: 0;
    background: transparent;
    color: var(--tpl-text-muted);
    width: 36px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
.tpl-view-toggle .tpl-vt-btn + .tpl-vt-btn { border-left: 1px solid var(--tpl-border); }
.tpl-view-toggle .tpl-vt-btn:hover { color: var(--tpl-text-2); }
.tpl-view-toggle .tpl-vt-btn.active { background: var(--tpl-primary-soft); color: var(--tpl-primary-ink); }

/* ── Mobile stacking for tpl tables ──
   Add .tpl-table-stack alongside .tpl-table, then annotate cells:
     data-th="Label"      -> label shown before the value on mobile
     .tpl-cell-primary    -> promoted to the card title (no label)
     .tpl-cell-actions    -> bottom action row, right-aligned
     .tpl-hide-sm         -> dropped entirely on mobile (e.g. "#")
   Desktop rendering is untouched. */
@media (max-width: 767.98px) {
    .tpl-table.tpl-table-stack thead { display: none; }
    .tpl-table.tpl-table-stack tbody,
    .tpl-table.tpl-table-stack tbody tr,
    .tpl-table.tpl-table-stack tbody td { display: block; width: 100%; }
    .tpl-table.tpl-table-stack tbody tr {
        padding: 12px 16px;
        border-bottom: 1px solid var(--tpl-border);
    }
    .tpl-table.tpl-table-stack tbody tr:last-child { border-bottom: 0; }
    .tpl-table.tpl-table-stack tbody tr:hover { background: transparent; }
    .tpl-table.tpl-table-stack tbody td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        border: 0 !important;
        padding: 3px 0;
        font-size: 13px;
        text-align: left !important;
        white-space: normal !important;
    }
    .tpl-table.tpl-table-stack tbody td[data-th]::before {
        content: attr(data-th);
        color: var(--tpl-text-3);
        font-size: 10.5px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .4px;
        flex-shrink: 0;
    }
    .tpl-table.tpl-table-stack tbody td.tpl-cell-primary {
        font-weight: 600;
        color: var(--tpl-text);
        font-size: 14px;
        padding-bottom: 4px;
    }
    .tpl-table.tpl-table-stack tbody td.tpl-cell-primary::before { display: none; }
    .tpl-table.tpl-table-stack tbody td.tpl-cell-actions {
        justify-content: flex-end;
        gap: 8px;
        border-top: 1px solid var(--tpl-line) !important;
        margin-top: 8px;
        padding-top: 10px;
    }
    .tpl-table.tpl-table-stack tbody td.tpl-cell-actions::before { display: none; }
    .tpl-table.tpl-table-stack tbody td.tpl-cell-actions .tpl-icon-btn {
        width: 38px;
        height: 38px;
        background: var(--tpl-bg-soft);
        font-size: 14px;
    }
    .tpl-table.tpl-table-stack .tpl-hide-sm { display: none !important; }
    .tpl-table.tpl-table-stack .tpl-empty { padding: 32px 16px; }
}

/* ============================================================================
   DATATABLES SKIN (jQuery DataTables + Buttons, Bootstrap4 flavour)
   ----------------------------------------------------------------------------
   Global chrome restyle: search box, length select, export buttons, info text,
   pagination, processing overlay. Loaded after the DataTables plugin CSS (see
   vendor/adminlte/page.blade.php) so these rules win.
   The table body itself only gets the tpl look when the table carries
   .tpl-table — public/js/tpl-datatable.js adds it automatically.
   ========================================================================== */

/* Layout wrappers (generated by the tplDataTable() default dom):
   .tpl-dt-card > [.tpl-card-head?] > .tpl-dt-top > .tpl-dt-tablewrap > .tpl-dt-bottom
   Toolbar, table and footer all live INSIDE one tpl-card, divider-separated. */
.tpl-dt-top {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    justify-content: space-between;
}
.tpl-dt-card .tpl-dt-top {
    padding: 12px 14px;
    border-bottom: 1px solid var(--tpl-line);
}
.tpl-dt-tools { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.tpl-dt-tablewrap { overflow-x: auto; position: relative; }
.tpl-dt-bottom {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    justify-content: space-between;
}
.tpl-dt-card .tpl-dt-bottom {
    padding: 10px 14px;
    border-top: 1px solid var(--tpl-line);
}

/* Length select */
.dataTables_wrapper .dataTables_length { margin: 0; }
.dataTables_wrapper .dataTables_length label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--tpl-text-3);
}
.dataTables_wrapper .dataTables_length select {
    border: 1px solid var(--tpl-border-strong);
    border-radius: var(--tpl-radius-sm);
    color: var(--tpl-text-2);
    background-color: var(--tpl-surface);
    padding: 4px 24px 4px 8px;
    height: 31px;
    font-size: 12.5px;
}
.dataTables_wrapper .dataTables_length select:focus {
    border-color: var(--tpl-primary-border);
    box-shadow: 0 0 0 3px var(--tpl-primary-focus);
    outline: 0;
}

/* Search box */
.dataTables_wrapper .dataTables_filter { margin: 0; }
.dataTables_wrapper .dataTables_filter label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--tpl-text-3);
}
.dataTables_wrapper .dataTables_filter input {
    border: 1px solid var(--tpl-border-strong);
    border-radius: var(--tpl-radius-sm);
    padding: 5px 12px;
    height: 31px;
    font-size: 13px;
    color: var(--tpl-text);
    background: var(--tpl-surface);
    margin-left: 0 !important;
    min-width: 190px;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.dataTables_wrapper .dataTables_filter input:focus {
    border-color: var(--tpl-primary-border);
    box-shadow: 0 0 0 3px var(--tpl-primary-focus);
    outline: 0;
}
.dataTables_wrapper .dataTables_filter input::placeholder { color: var(--tpl-text-muted); }

/* Export / colvis buttons */
.dataTables_wrapper .dt-buttons {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
}
.dataTables_wrapper .dt-buttons .btn {
    background: var(--tpl-surface) !important;
    color: var(--tpl-text-2) !important;
    border: 1px solid var(--tpl-border-strong) !important;
    border-radius: var(--tpl-radius-sm) !important;
    padding: 5px 12px !important;
    font-size: 12.5px !important;
    font-weight: 500 !important;
    line-height: 1.4 !important;
    box-shadow: none !important;
    margin: 0 !important;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.dataTables_wrapper .dt-buttons .btn:hover,
.dataTables_wrapper .dt-buttons .btn:focus {
    background: var(--tpl-bg-soft) !important;
    color: var(--tpl-text) !important;
    border-color: var(--tpl-text-muted) !important;
}
.dataTables_wrapper .dt-buttons .btn:focus { box-shadow: 0 0 0 3px var(--tpl-primary-focus) !important; }

/* Colvis dropdown collection */
.dt-button-collection {
    border: 1px solid var(--tpl-border) !important;
    border-radius: var(--tpl-radius) !important;
    box-shadow: var(--tpl-card-shadow) !important;
    padding: 6px !important;
    background: var(--tpl-surface) !important;
}
.dt-button-collection .dt-button,
.dt-button-collection .dropdown-item {
    border-radius: 6px !important;
    font-size: 13px !important;
    color: var(--tpl-text-2) !important;
    padding: 6px 10px !important;
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
}
.dt-button-collection .dt-button:hover,
.dt-button-collection .dropdown-item:hover { background: var(--tpl-bg-soft) !important; }
.dt-button-collection .dt-button.active,
.dt-button-collection .dropdown-item.active {
    background: var(--tpl-primary-soft) !important;
    color: var(--tpl-primary-ink) !important;
}

/* Info text */
.dataTables_wrapper .dataTables_info {
    padding-top: 0;
    margin: 0;
    font-size: 12px;
    color: var(--tpl-text-3);
}

/* Pagination pills */
.dataTables_wrapper .dataTables_paginate { margin: 0; padding-top: 0; }
.dataTables_wrapper .dataTables_paginate .pagination { margin: 0; gap: 4px; flex-wrap: wrap; }
.dataTables_wrapper .dataTables_paginate .page-item .page-link {
    border: 1px solid var(--tpl-border);
    border-radius: var(--tpl-radius-sm) !important;
    color: var(--tpl-text-2);
    background: var(--tpl-surface);
    font-size: 12.5px;
    padding: 4px 10px;
    min-width: 30px;
    text-align: center;
    box-shadow: none !important;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.dataTables_wrapper .dataTables_paginate .page-item .page-link:hover { background: var(--tpl-bg-soft); }
.dataTables_wrapper .dataTables_paginate .page-item.active .page-link {
    background: var(--tpl-primary);
    border-color: var(--tpl-primary);
    color: var(--tpl-on-primary);
}
.dataTables_wrapper .dataTables_paginate .page-item.disabled .page-link {
    color: var(--tpl-text-muted);
    background: var(--tpl-surface);
    border-color: var(--tpl-divider);
}

/* Processing overlay */
.dataTables_wrapper .dataTables_processing {
    background: rgba(255, 255, 255, .9) !important;
    border: 1px solid var(--tpl-border) !important;
    border-radius: var(--tpl-radius) !important;
    box-shadow: var(--tpl-card-shadow) !important;
    color: var(--tpl-text-2) !important;
    font-size: 13px;
    padding: 14px 18px !important;
}
.tpl-dt-spinner {
    width: 22px;
    height: 22px;
    margin: 0 auto;
    border: 3px solid var(--tpl-primary-soft);
    border-top-color: var(--tpl-primary);
    border-radius: 50%;
    animation: tplDtSpin .7s linear infinite;
}
@keyframes tplDtSpin { to { transform: rotate(360deg); } }

/* Table body — only when the table carries .tpl-table (added by tplDataTable) */
table.dataTable.tpl-table { border-collapse: collapse !important; margin: 0 !important; }
table.dataTable.tpl-table thead th {
    position: relative;
}
table.dataTable.tpl-table thead .sorting:before,
table.dataTable.tpl-table thead .sorting:after,
table.dataTable.tpl-table thead .sorting_asc:before,
table.dataTable.tpl-table thead .sorting_asc:after,
table.dataTable.tpl-table thead .sorting_desc:before,
table.dataTable.tpl-table thead .sorting_desc:after {
    color: var(--tpl-text-muted);
    opacity: .5;
}
table.dataTable.tpl-table thead .sorting_asc:before,
table.dataTable.tpl-table thead .sorting_desc:after {
    color: var(--tpl-primary-ink);
    opacity: 1;
}
table.dataTable.tpl-table tbody tr.selected,
table.dataTable.tpl-table tbody tr.shown { background: var(--tpl-primary-soft); }

/* Generic grid cards (tplDataTable auto-generated grid view) */
.tpl-dt-gcard {
    border: 1px solid var(--tpl-border);
    border-radius: var(--tpl-radius);
    background: var(--tpl-surface);
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    transition: box-shadow .18s ease, border-color .18s ease;
}
.tpl-dt-gcard:hover { border-color: var(--tpl-primary-border); box-shadow: var(--tpl-card-shadow); }
.tpl-gc-title { font-weight: 600; color: var(--tpl-text); font-size: .9rem; overflow-wrap: anywhere; }
.tpl-gc-label {
    display: block;
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .4px;
    color: var(--tpl-text-3);
    margin-bottom: 2px;
}
.tpl-gc-value { font-size: 13px; color: var(--tpl-text-2); overflow-wrap: anywhere; }
.tpl-gc-actions {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    border-top: 1px solid var(--tpl-line);
    padding-top: 10px;
    margin-top: auto;
}

/* Toolbar layout on mobile (only affects adapter-driven tables) */
@media (max-width: 767.98px) {
    /* Export / copy / print / column-visibility are desktop power-tools. On a
       phone the list already renders as cards (so "Columns" is meaningless) and
       the wrapped button rows just look cluttered — hide them. They return at
       >=768px. */
    .tpl-dt-top .dt-buttons { display: none !important; }
    /* Keep the length select + search on ONE compact row: "Show 10" stays
       auto-width on the left, the search box flexes to fill the rest. */
    .tpl-dt-top { flex-wrap: nowrap; gap: 8px; align-items: center; }
    .tpl-dt-tools { flex-shrink: 0; margin: 0; }
    .tpl-dt-search { flex: 1 1 auto; min-width: 0; }
    .tpl-dt-top .dataTables_filter,
    .tpl-dt-top .dataTables_filter label { width: 100%; }
    .tpl-dt-top .dataTables_filter input { width: 100%; min-width: 0; }
    /* Info + pagination still stack, centered, below the table. */
    .tpl-dt-bottom { flex-direction: column; align-items: stretch; }
    .tpl-dt-bottom .dataTables_info { text-align: center; }
    .tpl-dt-bottom .dataTables_paginate { display: flex; justify-content: center; }
}

/* ============================================================================
   DASHBOARD & WIDGET COMPONENTS (v2)
   Reusable on any dashboard: the school Command Center uses all of them, and
   module dashboards can adopt them without new CSS.
   ========================================================================== */

/* ── Page intro (greeting / title + context line + actions) ── */
.tpl-intro { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 24px; margin: 4px 0 20px; }
.tpl-intro-title { font-family: var(--tpl-font-heading); font-size: var(--tpl-fs-lg); font-weight: 650; color: var(--tpl-text); letter-spacing: var(--tpl-tracking-title); line-height: 1.3; margin: 0; }
.tpl-intro-sub { font-size: var(--tpl-fs-base); color: var(--tpl-text-3); margin: 4px 0 0; }
.tpl-intro-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* ── KPI cards ── */
.tpl-kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; margin-bottom: 20px; }
.tpl-kpi {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: var(--tpl-surface);
    border: 1px solid var(--tpl-border);
    border-radius: var(--tpl-radius);
    padding: 16px 18px;
    color: inherit;
    text-decoration: none !important;
    min-width: 0;
    transition: border-color .15s var(--tpl-ease), box-shadow .15s var(--tpl-ease);
}
a.tpl-kpi:hover { border-color: var(--tpl-border-strong); box-shadow: var(--tpl-shadow-1); }
a.tpl-kpi:focus-visible { outline: 2px solid var(--tpl-primary); outline-offset: 2px; }
.tpl-kpi-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.tpl-kpi-label { font-size: var(--tpl-fs-label); font-weight: 500; color: var(--tpl-text-label); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-kpi-value {
    font-family: var(--tpl-font-heading);
    font-size: var(--tpl-fs-kpi);
    font-weight: 650;
    color: var(--tpl-text);
    letter-spacing: -.02em;
    line-height: 1.2;
    margin-top: 8px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tpl-kpi-value small { font-size: 55%; font-weight: 600; color: var(--tpl-text-3); letter-spacing: 0; margin-left: 2px; }
.tpl-kpi-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: var(--tpl-fs-sm); color: var(--tpl-text-3); margin-top: 4px; min-height: 19px; }
.tpl-delta { display: inline-flex; align-items: center; gap: 3px; font-size: 12px; font-weight: 600; padding: 0 7px; border-radius: 999px; line-height: 1.6; }
.tpl-delta.is-up { background: var(--tpl-green-soft); color: var(--tpl-green); }
.tpl-delta.is-down { background: var(--tpl-red-soft); color: var(--tpl-red); }
.tpl-delta.is-flat { background: var(--tpl-divider); color: var(--tpl-text-label); }

/* ── Quick actions ── */
.tpl-quick { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px; }
.tpl-quick-item {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 52px;
    padding: 8px 12px;
    background: var(--tpl-surface);
    border: 1px solid var(--tpl-border);
    border-radius: 10px;
    color: var(--tpl-text) !important;
    font-size: var(--tpl-fs-label);
    font-weight: 550;
    line-height: 1.3;
    text-decoration: none !important;
    transition: border-color .15s var(--tpl-ease), background-color .15s var(--tpl-ease);
    cursor: pointer;
    text-align: left;
    width: 100%;
}
.tpl-quick-item:hover { border-color: var(--tpl-primary-border); background: var(--tpl-primary-soft); }
.tpl-quick-item:focus-visible { outline: 2px solid var(--tpl-primary); outline-offset: 2px; }
.tpl-quick-item .tpl-quick-ico {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--tpl-primary-soft);
    color: var(--tpl-primary-ink);
    font-size: 14px;
}
.tpl-quick-item:hover .tpl-quick-ico { background: var(--tpl-surface); }
.tpl-quick-item.is-more { color: var(--tpl-text-label) !important; border-style: dashed; background: transparent; }
.tpl-quick-item.is-more .tpl-quick-ico { background: var(--tpl-divider); color: var(--tpl-text-label); }

/* ── Section label above a block ── */
.tpl-section-label { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 0 10px; }
.tpl-section-label h2 { font-size: var(--tpl-fs-md); font-weight: 600; color: var(--tpl-text); margin: 0; letter-spacing: -.005em; }
.tpl-section-label a, .tpl-link { font-size: var(--tpl-fs-label); font-weight: 550; color: var(--tpl-primary-ink); }

/* ── Widget card helpers (on top of .tpl-card) ── */
.tpl-card-sub { font-size: var(--tpl-fs-sm); color: var(--tpl-text-3); margin-top: 1px; }
.tpl-card.is-fill { display: flex; flex-direction: column; height: 100%; }
.tpl-card.is-fill > .tpl-card-body { flex: 1 1 auto; }
.tpl-scroll { overflow-y: auto; scrollbar-width: thin; }

/* ── List rows (activity, dues, staff, exams…) ── */
.tpl-rows { margin: 0; padding: 0; list-style: none; }
.tpl-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--tpl-line); min-width: 0; }
.tpl-row:last-child { border-bottom: 0; }
.tpl-row.is-button { cursor: pointer; border-radius: 8px; margin: 0 -8px; padding-left: 8px; padding-right: 8px; }
.tpl-row.is-button:hover { background: var(--tpl-hover); }
.tpl-row-main { flex: 1 1 auto; min-width: 0; }
.tpl-row-title { font-size: var(--tpl-fs-base); font-weight: 550; color: var(--tpl-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-row-title.is-wrap { white-space: normal; }
.tpl-row-title strong { font-weight: 600; }
.tpl-row-sub { font-size: var(--tpl-fs-sm); color: var(--tpl-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-row-end { flex: 0 0 auto; text-align: right; font-size: var(--tpl-fs-label); color: var(--tpl-text-3); }
.tpl-row-amount { font-weight: 600; color: var(--tpl-text); font-variant-numeric: tabular-nums; }

/* ── Avatars & icon tiles ── */
.tpl-avatar {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--tpl-divider);
    color: var(--tpl-text-label);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
}
.tpl-ico.is-sm { width: 32px; height: 32px; border-radius: 8px; font-size: 13px; }

/* ── Meter (progress) ── */
.tpl-meter { height: 8px; border-radius: 999px; background: var(--tpl-divider); overflow: hidden; }
.tpl-meter > span { display: block; height: 100%; border-radius: inherit; background: var(--tpl-primary); }
.tpl-meter.is-green > span { background: var(--tpl-green); }
.tpl-meter.is-red > span { background: var(--tpl-red); }
.tpl-meter.is-sm { height: 6px; }

/* ── Mini stats (a row of labelled numbers inside a card) ── */
.tpl-mini-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); gap: 8px; }
.tpl-mini-stat { padding: 10px 12px; border-radius: 10px; background: var(--tpl-bg-soft); border: 1px solid var(--tpl-line); }
.tpl-mini-stat-value { font-size: 1.25rem; font-weight: 650; color: var(--tpl-text); font-variant-numeric: tabular-nums; line-height: 1.2; }
.tpl-mini-stat-label { font-size: 12px; color: var(--tpl-text-3); margin-top: 2px; }
.tpl-mini-stat.is-green .tpl-mini-stat-value { color: var(--tpl-green); }
.tpl-mini-stat.is-red .tpl-mini-stat-value { color: var(--tpl-red); }
.tpl-mini-stat.is-amber .tpl-mini-stat-value { color: var(--tpl-amber); }
.tpl-mini-stat.is-blue .tpl-mini-stat-value { color: var(--tpl-blue); }

/* ── Bar chart (plain DOM, real series only) ── */
.tpl-bars { display: flex; align-items: flex-end; gap: 6px; height: 168px; padding-top: 8px; }
.tpl-bar-col { flex: 1 1 0; min-width: 0; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 6px; }
/* Data marks use the chart series colour; the brand colour is for actions */
.tpl-bar { width: 100%; max-width: 28px; border-radius: 4px 4px 2px 2px; background: var(--tpl-chart-1); min-height: 2px; }
.tpl-bar.is-zero { background: var(--tpl-divider); }
.tpl-bar-lbl { font-size: 11px; color: var(--tpl-text-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.tpl-chart-summary { display: flex; flex-wrap: wrap; gap: 8px 28px; margin-bottom: 8px; }
.tpl-chart-summary strong { display: block; font-size: 1.125rem; font-weight: 650; color: var(--tpl-text); font-variant-numeric: tabular-nums; }
.tpl-chart-summary span { font-size: 12px; color: var(--tpl-text-3); }

/* ── Date tile (events, exams) ── */
.tpl-date {
    flex: 0 0 44px;
    width: 44px;
    border: 1px solid var(--tpl-border);
    border-radius: 10px;
    text-align: center;
    padding: 4px 0;
    background: var(--tpl-surface);
}
.tpl-date-day { font-size: 16px; font-weight: 650; color: var(--tpl-text); line-height: 1.2; font-variant-numeric: tabular-nums; }
.tpl-date-mon { font-size: 10.5px; font-weight: 600; color: var(--tpl-text-3); text-transform: uppercase; letter-spacing: .04em; }

/* ── Dashboard grid ── */
.tpl-dash-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 20px; align-items: stretch; margin-bottom: 20px; }
.tpl-dash-grid > * { min-width: 0; }
.tpl-span-3 { grid-column: span 3; }
.tpl-span-4 { grid-column: span 4; }
.tpl-span-5 { grid-column: span 5; }
.tpl-span-6 { grid-column: span 6; }
.tpl-span-7 { grid-column: span 7; }
.tpl-span-8 { grid-column: span 8; }
.tpl-span-12 { grid-column: span 12; }
@media (max-width: 1399.98px) {
    .tpl-span-3 { grid-column: span 6; }
}
@media (max-width: 1199.98px) {
    .tpl-span-4, .tpl-span-5, .tpl-span-7 { grid-column: span 6; }
    .tpl-span-8 { grid-column: span 12; }
}
@media (max-width: 767.98px) {
    .tpl-dash-grid { gap: 16px; }
    .tpl-dash-grid > * { grid-column: span 12; }
    .tpl-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
    .tpl-kpi { padding: 14px; }
    .tpl-kpi-value { font-size: 1.375rem; }
    .tpl-quick { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tpl-intro { margin-bottom: 16px; }
}

/* ── Checklist (setup status) ── */
.tpl-check { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--tpl-line); font-size: var(--tpl-fs-base); color: var(--tpl-text); }
.tpl-check:last-child { border-bottom: 0; }
.tpl-check-mark { flex: 0 0 22px; width: 22px; height: 22px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; background: var(--tpl-divider); color: var(--tpl-text-3); }
.tpl-check.is-done .tpl-check-mark { background: var(--tpl-green-soft); color: var(--tpl-green); }

/* ── Setup callout (incomplete configuration) ── */
.tpl-callout { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; padding: 14px 18px; border: 1px solid var(--tpl-amber-border); background: var(--tpl-amber-soft); border-radius: var(--tpl-radius); margin-bottom: 20px; color: #6b4907; }
.tpl-callout-title { font-weight: 650; color: var(--tpl-amber); }
.tpl-callout .tpl-meter { width: 160px; background: var(--tpl-amber-border); }
.tpl-callout .tpl-meter > span { background: var(--tpl-amber); }

/* ── Plain modal used by dashboards (no Bootstrap JS dependency) ── */
.tpl-overlay {
    position: fixed;
    inset: 0;
    z-index: 1060;
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding: 6vh 16px 16px;
    background: rgba(11, 18, 38, .45);
    overflow-y: auto;
}
.tpl-overlay.is-open { display: flex; }
.tpl-dialog {
    width: 100%;
    max-width: 880px;
    background: var(--tpl-surface);
    border-radius: var(--tpl-radius-lg);
    box-shadow: var(--tpl-shadow-3);
    display: flex;
    flex-direction: column;
    max-height: 88vh;
}
.tpl-dialog.is-sm { max-width: 640px; }
.tpl-dialog-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 18px 24px 14px; border-bottom: 1px solid var(--tpl-line); }
.tpl-dialog-title { font-size: 1.0625rem; font-weight: 600; color: var(--tpl-text); margin: 0; }
.tpl-dialog-body { padding: 16px 24px 24px; overflow-y: auto; }
@media (max-width: 575.98px) {
    .tpl-overlay { padding: 0; align-items: flex-end; }
    .tpl-dialog { border-radius: 18px 18px 0 0; max-height: 92vh; }
    .tpl-dialog-head, .tpl-dialog-body { padding-left: 16px; padding-right: 16px; }
}

/* ── v3 dashboard pieces (reference-aligned) ─────────────────────────────── */

/* Solid icon tile (white icon on a colour square) — KPI cards, pipelines */
.tpl-tile {
    flex: 0 0 36px;
    width: 36px;
    height: 36px;
    border-radius: var(--tpl-radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 15px;
    background: var(--tpl-tile-slate);
}
.tpl-tile.is-blue { background: var(--tpl-tile-blue); }
.tpl-tile.is-green { background: var(--tpl-tile-green); }
.tpl-tile.is-amber { background: var(--tpl-tile-amber); }
.tpl-tile.is-violet { background: var(--tpl-tile-violet); }
.tpl-tile.is-red { background: var(--tpl-tile-red); }
.tpl-tile.is-teal { background: var(--tpl-tile-teal); }
.tpl-tile.is-primary { background: var(--tpl-primary); color: var(--tpl-on-primary); }
.tpl-tile.is-outline { background: var(--tpl-surface); color: var(--tpl-text-label); border: 1px solid var(--tpl-border); }
.tpl-tile.is-lg { width: 40px; height: 40px; flex-basis: 40px; font-size: 16px; }

/* KPI variants */
.tpl-kpi.is-feature .tpl-kpi-value { font-size: 1.75rem; }
.tpl-kpi .tpl-kpi-head .tpl-tile { order: 2; }
.tpl-kpi-stack { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.tpl-kpi-col { display: flex; flex-direction: column; gap: 16px; }

/* Stat box — bordered cell with label / value / caption */
.tpl-statbox-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.tpl-statbox-grid.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tpl-statbox { border: 1px solid var(--tpl-border); border-radius: var(--tpl-radius-sm); padding: 10px 12px; min-width: 0; background: var(--tpl-surface); }
.tpl-statbox.is-center { text-align: center; }
.tpl-statbox-label { font-size: 12.5px; color: var(--tpl-text-3); }
.tpl-statbox-value { font-family: var(--tpl-font-heading); font-size: 1.25rem; font-weight: 650; color: var(--tpl-text); font-variant-numeric: tabular-nums; line-height: 1.3; margin-top: 2px; }
.tpl-statbox-sub { font-size: 12.5px; color: var(--tpl-text-3); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-statbox.is-green .tpl-statbox-value { color: var(--tpl-green); }
.tpl-statbox.is-red .tpl-statbox-value { color: var(--tpl-red); }
.tpl-statbox.is-amber .tpl-statbox-value { color: var(--tpl-amber); }

/* Accent call-to-action card (one per dashboard) */
.tpl-cta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 20px;
    border-radius: var(--tpl-radius);
    background: var(--tpl-primary);
    color: var(--tpl-on-primary);
}
.tpl-cta-title { font-family: var(--tpl-font-heading); font-size: var(--tpl-fs-md); font-weight: 650; margin: 0; color: inherit; }
.tpl-cta-sub { font-size: var(--tpl-fs-label); opacity: .9; margin: 2px 0 0; }
.tpl-cta .btn-cta {
    display: inline-flex; align-items: center; gap: 6px;
    /* Inverse of the card: readable on any brand colour, and on the light
       Ink primary in dark mode (a white button on a white card vanished). */
    background: var(--tpl-on-primary); color: var(--tpl-primary) !important; border: 0;
    border-radius: var(--tpl-radius-sm); padding: 7px 14px;
    font-weight: 600; font-size: var(--tpl-fs-label); white-space: nowrap;
    text-decoration: none !important;
}
.tpl-cta .btn-cta:hover { opacity: .9; }

/* Dark highlight card (one per dashboard) — deep navy in both themes */
.tpl-highlight {
    border-radius: var(--tpl-radius);
    overflow: hidden;
    border: 1px solid var(--tpl-border);
    background: var(--tpl-surface);
    height: 100%;
    display: flex;
    flex-direction: column;
}
/* The one "brand panel" card on a dashboard: the same surface as the sign-in
   brand panel — ink by default, the preset or school colour when one is set. */
.tpl-highlight-top { background: var(--tpl-brand-surface, #18181b); color: var(--tpl-on-brand-surface, #fafafa); padding: 18px 20px; }
.tpl-highlight-label { font-size: var(--tpl-fs-label); color: inherit; opacity: .78; }
.tpl-highlight-value { font-family: var(--tpl-font-heading); font-size: 1.75rem; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.2; overflow-wrap: anywhere; }
/* Wraps instead of squeezing: three amounts side by side collided on phones */
.tpl-highlight-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 12px 16px; margin-top: 16px; }
.tpl-highlight-row .tpl-highlight-value { font-size: 1.25rem; }
.tpl-highlight .btn-on-dark {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--tpl-on-brand-surface, #fafafa); color: var(--tpl-brand-surface, #18181b) !important; border: 0; border-radius: var(--tpl-radius-sm);
    padding: 6px 12px; font-size: var(--tpl-fs-label); font-weight: 650; text-decoration: none !important; white-space: nowrap;
}
.tpl-highlight-body { padding: 16px 20px 18px; flex: 1 1 auto; }

/* Pipeline boxes (count + label + coloured progress underline) */
.tpl-pipes { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.tpl-pipe { border: 1px solid var(--tpl-border); border-radius: var(--tpl-radius-sm); padding: 12px; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.tpl-pipe-top { display: flex; align-items: center; gap: 10px; }
.tpl-pipe-value { font-size: 1.375rem; font-weight: 650; color: var(--tpl-text); line-height: 1.1; font-variant-numeric: tabular-nums; }
.tpl-pipe-label { font-size: 12.5px; color: var(--tpl-text-3); }
.tpl-pipe-bar { height: 3px; border-radius: 3px; background: var(--tpl-divider); overflow: hidden; }
.tpl-pipe-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--tpl-tile-green); }
.tpl-pipe-bar.is-violet > span { background: var(--tpl-tile-violet); }
.tpl-pipe-bar.is-blue > span { background: var(--tpl-tile-blue); }
.tpl-pipe-bar.is-red > span { background: var(--tpl-tile-red); }
.tpl-pipe-bar.is-amber > span { background: var(--tpl-tile-amber); }

/* CSS donut (conic-gradient; values are always also printed in the legend) */
.tpl-donut-wrap { display: flex; align-items: center; gap: 20px; }
.tpl-donut {
    --donut-size: 136px;
    flex: 0 0 var(--donut-size);
    width: var(--donut-size);
    height: var(--donut-size);
    border-radius: 50%;
    position: relative;
    background: var(--tpl-divider);
}
.tpl-donut::after {
    content: '';
    position: absolute;
    inset: 18px;
    border-radius: 50%;
    background: var(--tpl-surface);
}
.tpl-donut-center { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.tpl-donut-center strong { font-size: 1.25rem; font-weight: 650; color: var(--tpl-text); font-variant-numeric: tabular-nums; line-height: 1.2; }
.tpl-donut-center span { font-size: 11.5px; color: var(--tpl-text-3); }
.tpl-legend { flex: 1 1 auto; min-width: 0; margin: 0; padding: 0; list-style: none; }
.tpl-legend li { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: var(--tpl-fs-label); color: var(--tpl-text-2); }
.tpl-legend li strong { margin-left: auto; font-weight: 600; color: var(--tpl-text); font-variant-numeric: tabular-nums; }
.tpl-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px; background: var(--tpl-text-muted); }
@media (max-width: 400px) { .tpl-donut-wrap { flex-direction: column; align-items: stretch; } .tpl-donut { margin: 0 auto; } }

/* Bars: highlight low values */
.tpl-bar.is-low { background: var(--tpl-tile-amber); }
.tpl-bar.is-soft { background: var(--tpl-chart-1); opacity: .85; }
.tpl-bars.is-compact { height: 110px; }
.tpl-highlight .tpl-bars { height: 96px; }
.tpl-highlight .tpl-bar { background: var(--tpl-chart-1); }
.tpl-highlight .tpl-bar.is-zero { background: var(--tpl-divider); }

/* Card head with a trailing button */
.tpl-card-head .btn-xs, .tpl-card-head .tpl-head-btn {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 12.5px; font-weight: 550; padding: 3px 10px;
    border: 1px solid var(--tpl-border); border-radius: var(--tpl-radius-sm);
    color: var(--tpl-text-2) !important; background: var(--tpl-surface); text-decoration: none !important; white-space: nowrap;
}
.tpl-card-head .tpl-head-btn:hover { background: var(--tpl-hover); color: var(--tpl-text) !important; }
.tpl-live { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 550; color: var(--tpl-green); background: var(--tpl-green-soft); border-radius: var(--tpl-radius-xs); padding: 1px 8px; }

/* ==========================================================================
   Module guide hero (.fx-hero, the "How it works" pages of every module).
   Each guide styles it inline; these rules (body-scoped, so they out-rank the
   page's own) put it on the brand surface like the dashboard highlight card:
   Ink by default, the school colour when one is set. Text uses the matching
   on-colour, so a light school colour still reads.
   ========================================================================== */
body .fx-hero { background: var(--tpl-brand-surface, #18181b); box-shadow: none; border-radius: var(--tpl-radius-lg); }
body .fx-hero::before, body .fx-hero::after { display: none; }
body .fx-hero-inner, body .fx-hero-title, body .fx-hero-sub strong, body .fx-stat b { color: var(--tpl-on-brand-surface, #fafafa); }
body .fx-hero-title { font-family: var(--tpl-font-heading); font-weight: 650; letter-spacing: -0.01em; }
body .fx-hero-title span { background: none; -webkit-text-fill-color: currentColor; color: inherit; text-decoration: underline; text-decoration-thickness: 3px; text-underline-offset: 6px; text-decoration-color: color-mix(in srgb, var(--tpl-on-brand-surface, #fafafa) 45%, transparent); }
body .fx-hero-sub, body .fx-stat span { color: color-mix(in srgb, var(--tpl-on-brand-surface, #fafafa) 80%, transparent); }
body .fx-badge, body .fx-stat {
    background: color-mix(in srgb, var(--tpl-on-brand-surface, #fafafa) 10%, transparent);
    border-color: color-mix(in srgb, var(--tpl-on-brand-surface, #fafafa) 18%, transparent);
    color: var(--tpl-on-brand-surface, #fafafa);
    backdrop-filter: none;
}
body .fx-stat span { text-transform: none; font-size: 12px; }
